基于STM32F103——SIM900A发送短信+串口打印

这篇具有很好参考价值的文章主要介绍了基于STM32F103——SIM900A发送短信+串口打印。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


最近用STM32F103做一个智能门锁小玩意,密码输入错误次数多进行验证码解锁,这里我采用SIM900A来通过发送短信输入验证码进行解锁。就是简单的了解了一下在这里也单独的写写这个SIM900A的一写笔记。

基本介绍

基于STM32F103——SIM900A发送短信+串口打印
。。。。。。还是直接进入主题吧

一:单独测试

SIM900A是可以AT指令操作的,所以一般我拿到这种模块就是先单独的测试一下这个模块是否正常。通过一个USB-TTL 和 SIM900A连接 进行调试。用我们的电脑串口助手测试即可。没必要上来就用单片机,现单独测试了先。没问题再转成代码也不迟。

1.准备工作

USB-TTL一个
基于STM32F103——SIM900A发送短信+串口打印
还有杜邦线就不用说啦

2.接线

USB-TTL SIM900A
5V VCC5
GND GND
TX 5VR
RX 5VT

3.指令操作

打开你的串口助手
注意:建议使用卖家配套的串口助手
注意:建议使用卖家配套的串口助手
注意:建议使用卖家配套的串口助手

第一步:发送AT检测是否正常 (记得要回车换行再发送) 成功返回OK

AT

第二步:选择短消息格式(0:PDU模式 1:文本模式) (记得要回车换行再发送) 成功返回OK

AT+CMGF=1

第三步:选择TE字库集 (记得要回车换行再发送) 成功返回OK

AT+CSCS="UCS2"

第四步:保存SMS设置 (记得要回车换行再发送) 成功返回OK

AT+CSCA?

第五步:设置短消息文本模式参数 (记得要回车换行再发送) 成功返回OK

AT+CSMP=17,167,0,25

**第六步:设置接收短信方的电话号码(要转UNICON编码) (记得要回车换行再发送) 成功返回>**不知道咋转往下翻有一个代码是生成的。

AT+CMGS="你接收短信方的电话号码的UNICON编码"

第七步:发送要发送的内容(要转UNICON编码)(记得要回车换行再发送)成功返回>

"发送的内容的UNICON编码"

第八步:发送结束标志 16进制:0X1A 切换到16进制模式发送(不需要回车换行) 成功返回OK

1A

提示:
1.不出意外的话你设置接收短信的手机号码就能接收到你发送的短信内容

2.上面提到的为啥最好用卖家提供的串口助手呢 因为我一开始就没用卖家的,我用的其他,换了2个都是发送最后的1A 返回的error 而不是OK。后来用回他们提供的就成功了。

3.关于UNICON编码转换软件 一般卖家都会提供资料的 如下图
你没有也没关系 或者懒得找咱就自己写一个 我这里也有写 请忘下看 不过我这里是ASCII转Unicode 如果是中文你可以自己写一下 或者还是找软件转吧 哈哈哈哈
基于STM32F103——SIM900A发送短信+串口打印

4.测试结果

基于STM32F103——SIM900A发送短信+串口打印

二:关于Unicode编码

Unicode基本介绍

Unicode一般指统一码,也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

1、编码方式
unicode是一种国际组织制定能容纳所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

我们看图 我这里只是ASCII转… 凑合看吧
我们把ASCII字符串用当成双字节汉字转unicode码你发现1这个字符变成了0031
这31是不是你想到了什么,1的16进制不就是0X31吗?前面补2个0后面是它的16进制不就完事了么?
基于STM32F103——SIM900A发送短信+串口打印

/**********************************************************************
描述: ASCII 转 unicode      比如 '1'  转成 "0031"
***********************************************************************/
void ASCII_TO_Unicode(char *ASCII,char *Unicode)
{
    int length;
    int i = 0;
    int j = 0;
	memset(Unicode,'\0',sizeof(Unicode));
    length = strlen(ASCII);

    for(i=0;i<length;i++)
    {
        Unicode[j++] = '0';
        Unicode[j++] = '0';

        Unicode[j++] = (ASCII[i] / 16) + 0x30;
        Unicode[j++] = (ASCII[i] % 16) + 0x30;
    }

}

比如我想把接收短信方的电话号码转一下
基于STM32F103——SIM900A发送短信+串口打印

三:代码编写

有了刚才的测试,我们就可以转成代码来 用STM32F103来控制SIM900A发送短信了。

我这里不加入显示屏来了。直接用串口打印信息查看了。

用到资源:两个串口
串口1用于打印信息(充当显示屏)
串口2用于和SIM900A通信。

sim900a.c

#include "sim900a.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usart.h"
#include "delay.h"



uint8_t verification_code[7];		//存放验证码 




uint8_t sim900a_receive_data[128] = {0};
uint16_t sim900a_receive_count;




/**********************************************************************
描述:   SIM900A模块发送指令 函数
参数: *str:指令内容	ack:正常返回结果的数据 time:允许时间(1次代表 10ms)
返回: 0:指令得到正确回应 1: 指令没得到回应
***********************************************************************/
uint8_t sim900a_send_cmd(uint8_t *str,uint8_t *ack,uint16_t time)
{
	memset(sim900a_receive_data,'\0',sizeof(sim900a_receive_data));
	sim900a_receive_count = 0;
	
	usart_sendString(USART2,(char *)str);		//发送指令
	if(ack == NULL)	return 0;
	
	//开启中断接收
	OPEN_USART2_RECEIVE;
	while(time--)
	{
		delay_ms(10);
		//寻找要找的关键词 找到关中断接收 并且返回0
		if(strstr((char *)sim900a_receive_data,(char *)ack) != NULL)
		{
			CLOSE_USART2_RECEIVE;	//关闭中断接收
			return 0;
		}	
	}
	
	CLOSE_USART2_RECEIVE;	//关闭中断接收
	return 1;				//超时还没收到想要得到的关键词 关串口中断 并且返回1			
}


/**********************************************************************
描述:   SIM900A模块发送指令 函数
参数: *str:指令内容	ack:正常返回结果的数据 time:允许时间(1次代表 10ms)
返回: 0:指令得到正确回应 1: 指令没得到回应
***********************************************************************/
uint8_t sim900a_send_end(uint8_t data,uint8_t *ack,uint16_t time)
{
	sim900a_receive_count = 0;	
	memset(sim900a_receive_data,'\0',sizeof(sim900a_receive_data));
	

	usart_sendByte(USART2,data);		//发送结束指令
	if(ack == NULL)	return 0;
	
	//开启中断接收
	OPEN_USART2_RECEIVE;
	
	while(time--)
	{
		delay_ms(10);
		//寻找要找的关键词 找到关中断接收 并且返回0
		if(strstr((char *)sim900a_receive_data,(char *)ack) != NULL)
		{
			CLOSE_USART2_RECEIVE;	//关闭中断接收
			return 0;
		}	
	}
	CLOSE_USART2_RECEIVE;		//关闭中断接收
	return 1;					//超时还没收到想要得到的关键词 关串口中断 并且返回1			
}



/**********************************************************************
描述:   随机生成验证码('0'~'9')
        产生字符 '0' ~ '9'  十进制也就是 48 ~ 57
***********************************************************************/
void generate_verification_code(char *data,uint8_t number)
{
    uint8_t i;
//    srand(time(NULL));

    for(i=0;i<number;i++)
    {
        data[i] = 48 + (rand() % 10);
    }
}

/**********************************************************************
描述: ASCII 转 unicode      比如 '1'  转成 "0031"
***********************************************************************/
void ASCII_TO_Unicode(char *ASCII,char *Unicode)
{
    int length;
    int i = 0;
    int j = 0;
	memset(Unicode,'\0',sizeof(Unicode));
    length = strlen(ASCII);

    for(i=0;i<length;i++)
    {
        Unicode[j++] = '0';
        Unicode[j++] = '0';

        Unicode[j++] = (ASCII[i] / 16) + 0x30;
        Unicode[j++] = (ASCII[i] % 16) + 0x30;
    }

}

/**********************************************************************
描述: SIM900A 发送验证码 函数
返回: 0:成功 1:失败
***********************************************************************/
uint8_t sim900a_send_verification_code(void)
{
	uint8_t ack;		//存放状态
	uint8_t err = 3;	//设置可错误次数 
	uint8_t send_count = 3;	//发送次数 发送次数达到还是没成功则放弃发送
	uint8_t sim900a_send_buffer[96] = {0};

SEND_AT:
	strcpy((char *)sim900a_send_buffer,"AT+CMGS=\"");
	
	//发送指令AT 检测是否返回OK 给300ms时间检测
	ack = sim900a_send_cmd(SIM900A_SEND_AT,"OK",30);	
	if(ack)
	{
		if(err-- == 0)
		{
			printf("AT FAIL\r\n");
			return 1;	
		}
		goto SEND_AT;
	}
	printf("AT OK\r\n");
	err = 3;
		
	//发送 短消息格式 指令 检测是否返回OK 给300ms时间检测
SELECT_SMS_FORMAT:
	ack = sim900a_send_cmd(SIM900A_SELECT_SMS_FORMAT,"OK",30);	
	if(ack)
	{
		if(err-- == 0)
		{
			printf("SMS FORMAT FAIL\r\n");	
			return 1;	
		}
		goto SELECT_SMS_FORMAT;
	}
	printf("SMS FORMAT SUCCESS\r\n");
	err = 3;



	//发送 选择TE字库集 指令 检测是否返回OK 给300ms时间检测
SELECT_TE_FONT:
	ack = sim900a_send_cmd(SIM900A_SELECT_TE_FONT,"OK",30);	
	if(ack)
	{
		if(err-- == 0)
		{
			printf("SELECT_TE_FONT FAIL\r\n");
			return 1;	
		}
		goto SELECT_TE_FONT;
	}
	printf("SELECT_TE_FONT SUCCESS\r\n");
	err = 3;



	//发送 选择TE字库集 指令 不检测返回值
SAVE_SMS_SET:
	ack = sim900a_send_cmd(SIM900A_SAVE_SMS_SET,NULL,0);	
	if(ack)
	{
		if(err-- == 0)
		{
			printf("SAVE_SMS_SET FAIL\r\n");
			return 1;	
		}
		goto SAVE_SMS_SET;
	}
	printf("SAVE_SMS_SET SUCCESS\r\n");
	err = 3;


	//发送 设置短消息文本模式参数 指令 检测是否返回OK 给300ms时间检测
SET_SMS_TEST_MODE:
	ack = sim900a_send_cmd(SIM900A_SET_SMS_TEST_MODE,"OK",30);	
		if(ack)
		{
			if(err-- == 0)
			{
				printf("SMS TEST MODE FAIL\r\n");
				return 1;	
			}
			goto SET_SMS_TEST_MODE;
		}
		printf("SMS TEST MODE SUCCESS\r\n");
		err = 3;


	//让我们的设置接收短信方电话号码生成unicode编码	
	ASCII_TO_Unicode(PHONE_NUMBER,&sim900a_send_buffer[strlen(sim900a_send_buffer)]);
	strcat((char *)sim900a_send_buffer,"\"\r\n"); 		
	printf("%s\r\n",sim900a_send_buffer);
	//发送 接收短信方电话号码 指令 检测是否返回OK 给1000ms时间检测
SELECT_PHONE_NUMBER:
	ack = sim900a_send_cmd(sim900a_send_buffer,">",100);	
		if(ack)
		{
			if(err-- == 0)
			{
				printf("SET PHONE NUMBER FAIL\r\n");
				return 1;	
			}
			goto SELECT_PHONE_NUMBER;
		}
		printf("SET PHONE NUMBER SUCCESS\r\n");
		err = 3;		
		
		//清空缓冲区 准备为发送验证码做准备
		memset(sim900a_send_buffer,'\0',sizeof(sim900a_send_buffer));
		
		

		
		//在这里开始就是开始发送内容了
		//1-生成验证码
		strcpy((char *)sim900a_send_buffer,"9A8C8BC17801003A");	//添加unicode码 "验证码:"
		generate_verification_code((char *)verification_code,6);//生成验证码
		printf("验证码生成结果:%s\r\n",verification_code);		
		
		//2-将随机产生的6位验证码转Unicode编码 并且拼接一起
		ASCII_TO_Unicode((char *)verification_code,&sim900a_send_buffer[strlen(sim900a_send_buffer)]);
		strcat((char *)sim900a_send_buffer,"\r\n");	//加上回车换行 
		printf("%s\r\n",sim900a_send_buffer);
		//3-发送数据
SEND_DATA:
	ack = sim900a_send_cmd(sim900a_send_buffer,">",300);	
		if(ack)
		{
			if(err-- == 0)
			{
				printf("SEND DATA FAIL\r\n");
				return 1;	
			}
			goto SEND_DATA;
		}
		printf("SEND DATA SUCCESS\r\n");
		
		//4-发送 0X1A 标志
		ack = sim900a_send_end(0x1a,"OK",800);
		if(ack)
		{
			if(send_count-- == 0)	return 1;
			memset(sim900a_send_buffer,'\0',sizeof(sim900a_send_buffer));
			err = 3;
			goto SEND_AT;	//重发短信
		}
		
		printf("SEND MESSAGE SUCCESS\r\n");
	return 0;
}


/**********************************************************************
描述: SIM900A 初始化 函数
返回: 0:成功 1:失败
***********************************************************************/
uint8_t sim900a_init(void)
{
	uint8_t ack;		//存放状态
	uint8_t err;		//设置可错误次数 

	err = 3;
	//发送指令AT 检测是否返回OK 给300ms时间检测
SEND_AT:
	
	ack = sim900a_send_cmd(SIM900A_SEND_AT,"OK",30);	
		if(ack)
		{
			if(err-- == 0)
			{
				printf("AT FAIL\r\n");				//ESP8266模块不存在
				return 1;	
			}

			goto SEND_AT;
		}
		printf("AT SUCCESS\r\n");
		
	return 0;
}




sim900a.h

#ifndef __SIM900A_H
#define __SIM900A_H
#include "stm32f10x.h"

/*用户必改 xxxxxxxxxxx 改成接收短信的电话号码*/
#define		PHONE_NUMBER		"xxxxxxxxxxx"


#define		SIM900A_SEND_AT							"AT\r\n"
//1.选择短消息格式 (0:PDU模式 1:文本模式)
#define		SIM900A_SELECT_SMS_FORMAT				"AT+CMGF=1\r\n"			
//2.选择TE字库集
#define		SIM900A_SELECT_TE_FONT					"AT+CSCS=\"UCS2\"\r\n"
//3.保存SMS设置
#define		SIM900A_SAVE_SMS_SET					"AT+CSCA?\r\n"
//4.设置短消息文本模式参数
#define		SIM900A_SET_SMS_TEST_MODE				"AT+CSMP=17,167,0,25\r\n"



extern uint8_t  sim900a_receive_data[128];
extern uint16_t  sim900a_receive_count;

extern uint8_t verification_code[7];		//存放验证码



uint8_t sim900a_send_cmd(uint8_t *str,uint8_t *ack,uint16_t time);	//SIM900A模块发送字符串指令 函数
uint8_t sim900a_send_end(uint8_t data,uint8_t *ack,uint16_t time);	//SIM900A模块发送单字节指令 函数
void generate_verification_code(char *data,uint8_t number);			// 随机生成验证码('0'~'9')
void ASCII_TO_Unicode(char *ASCII,char *Unicode);					// ASCII 转 unicode
uint8_t sim900a_init(void);
uint8_t sim900a_send_verification_code(void);
#endif

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "sim900a.h"

/*
注意:先到 sim900a.h 填写接收短信的电话号码。 

接线:
STM32F103		SIM900A
PA2				5VR
PA3				5VT
5V				5V
GND				GND
*/

int  main()
{
	usart1_init(115200);	//串口1初始化 用于打印信息
	usart2_init(115200);	//串口2初始化 用于和SIM900A模块
	
	do
	{
		printf("SIM900A Init...\r\n");
	}
	while(sim900a_init());
	
	
	printf("SIM900A Init Success\r\n");
	
	if(sim900a_send_verification_code())
	{
		printf("发送短信失败\r\n");
	}
	else
	{
		printf("发送短信成功\r\n");
	}
	
	while(1);
}



项目演示

基于STM32F103——SIM900A发送短信+串口打印

总结

问题1:一开始我采用电脑串口助手单独测试的时候,用了两个串口助手都到最后一步 发送 0x1A 时候返回error,以为是这个模块有问题,然后用回商家给的那个就成功了。。。。。所以还是建议用商家给的那个串口助手吧。。。。

问题2:如果发送失败,也有可能是你手机欠费了 哈哈哈哈哈哈哈。啊,我就是。擦。整我半天。

如果我哪里写的有问题,或者不好,请大家多多指教

#整个工程代码。
printf("+meQ:844797079\n")

如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈

继续加油!!!文章来源地址https://www.toymoban.com/news/detail-411175.html

到了这里,关于基于STM32F103——SIM900A发送短信+串口打印的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32驱动串口屏,STM32F103C8T6串口发送指令控制HMI串口屏

    串口屏是一个集成了单片机的屏幕模块,采用的是TTL串口协议,可以直接通过对应指令控制屏幕, 本文采用的串口屏是陶晶驰T0系列的基本型,目的是通过单片机的串口来控制串口屏 上面仅是一部分常用的基础指令,更多更仔细的指令或者函数可以访问陶晶驰资料官网。 硬

    2024年02月13日
    浏览(49)
  • 基于stm32F103的座面声控台灯

            设计一个放置在桌面使用的台灯,使用220v交流电供电。具备显示屏能够实时显示日期(年、月、日和星期),时间(小时、分钟、秒)和温度(摄氏度);能够通过语音交互播报实时日期、时间或者温度;能够通过语音交互控制桌面台灯的开启与关闭(或者明暗

    2024年04月29日
    浏览(73)
  • 基于STM32F103——AS608指纹模块+串口打印

    最近用STM32F103做一个智能门锁小玩意,其中用到指纹模块,我这里也单独的写一下笔记,不过我只是了解了基本的,就是我做门禁卡要用到的几个东西,其它还没了解。为了方便,做一下记录。我这里没有用到按键和显示屏,所以还是串口输出输入来控制了 哈哈哈哈 这里就

    2023年04月09日
    浏览(49)
  • 基于stm32F103的蜂鸣器周期发声实验

    蜂鸣器作为一种声音报警器件,应用广泛。本实验基于stm32F103单片机,通过控制蜂鸣器的IO口电平电压,使其周期性地进行电平翻转,从而驱动蜂鸣器发出周期性的鸣叫声。该实验主要运用了stm32的GPIO和定时器TIM的相关功能,不仅可以巩固这些外设的使用,也可以通过改变时间参数,控

    2024年02月21日
    浏览(48)
  • 全网最全的MCU面试经(基于STM32F103)

    提示:写本文章的缘由:本人在秋招时复习STM32有关的知识点,便顺势记录下来。本文章的知识均属于各大论坛的大佬回答,其中也有我的一些补充,本文主要以自己对STM32的理解作为框架,并积极整理各个大佬的文章,因此属于借花献佛,也不存在任何牟利,分享的初衷是便

    2024年02月09日
    浏览(45)
  • 基于STM32F103HAL库的声音定位系统

    这是一道学校出的电赛题目,要求在100*100cm的平面上实现定位实现声音定位。由于一米太大了,我们就做了40cm的,下面的讲解我按照40厘米的写。用到的处理器是stm32f103c8t6接下来分享一下调试心得。 硬件部分需要制作发声装置和接收装置,详细可以

    2024年02月14日
    浏览(59)
  • 2021校赛基于stm32f103多功能台灯

    起源 又到了一学期一次的校内电子设计大赛,又到了激动人心的时刻每次电子设计大赛都会出现各种大佬展现他们的作品,对于我这种菜鸟也只能默默观望,但是呢,积极参与还是要有的,记得上一次参加做的基于51的避障小车直接买的套件焊好 然后在烧入程序就直接上战场

    2023年04月20日
    浏览(55)
  • STM32--基于STM32F103的MAX30102心率血氧测量

    本文介绍基于STM32F103ZET6+MAX30102心率血氧测量+0.96寸OLED(7针)显示(完整程序代码见文末链接) 一、简介 MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块。它集成了一个红光LED和一个红外光LED、光电检测器、光器件,以及带环境光抑制的低噪声电子电路。 MA

    2024年01月16日
    浏览(51)
  • stm32f103基于pid的蓝牙循迹小车

    目录 前言 一、霍尔编码器以及定时器计数原理 二、使用pwm占空比对电机速度进行控制 三、使用systick的中断函数进行pid和速度的计算,还有oled的显示 四、常用的测速方法:  五、pid原理 六、oled的实现 七、蓝牙通信 八、3路循迹模块 总结   经过一个月对stm32的学习,终于完

    2024年02月16日
    浏览(45)
  • 基于STM32F103的PWM电机驱动A4950

    A4950的峰值输出电流可达±3.5 A,工作电压为7.6~40v。 优点:相对于L298N模块控制2个电机正反转仅需要4个I/O口,体积小,发热低。 缺点:需要2个PWM引脚才能控制正反转,所以控制2个电机需要4PWM引脚,会使用STM32F103芯片一个定时器的全部PWM通道。 A4950模块是靠输入2路的PWM占空

    2024年02月04日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包