平台:野火霸道开发板(STM32F103ZET6)
模块:SIM900A(大卡的SIM卡)
测试内容: STM32对GSM模块控制(串口2),控制其发送短信给10086(我用的移动卡),然后通过32转发接收,再把其内容发到串口1上
连接:
GSM模块上的STX <-> STM32 PA3; SRX <-> STM32 PA2; GND(GSM) <-> GND(开发板上随便一个地)
注意,GSM模块上有STX和MRX,这个M指的是MAX3232,是工业串口用的, S才是我们常用的TTL电平(有可能是MOS电平)
程序:
需要发送短信号码修改为10086
USART_Config();
配置串口1,主要是用来GSM与STM32通信的内容,通过串口1进行转发打印到串口助手上
GSM_USART_Config();
配置串口2,主要是通过STM32通过串口2对GSM模块进行AT控制发送指令
SysTick_Init();
系统滴答定时器,主要是用来做延时的,如后面的delay_ms
//检测模块响应是否正常
while(gsm_cmd("AT\r","OK",1000) != GSM_TRUE)
{
printf("\r\n模块响应测试不正常!!\r\n");
printf("\r\n若模块响应测试一直不正常,请检查模块的连接或是否已开启电源开关\r\n");
}
gsm_cmd("AT\r","OK",1000)
通过这个封装好的函数, stm32通过串口2,对GSM发送 'AT\r' 指令,
发送之后,再通过里面的
gsm_cmd_check(reply);
进行对接收数据的判断,判断接收到GSM返回来的指令是不是"OK",是OK就返回正常(GSM_TRUE)
如果返回不是OK, 串口1就会输出
printf("\r\n模块响应测试不正常!!\r\n");
printf("\r\n若模块响应测试一直不正常,请检查模块的连接或是否已开启电源开关\r\n");
如果串口没有打印上面的信息,那么就是正常,证明连接上了GSM了
如果错误,检测下你是不是接错线,或者漏了接GND-GND的线,又或者没有插入SIM卡
printf("\r\n通过了模块响应测试\r\n");
printf("\r\n正在等待GSM模块初始化...\r\n");
while(IsInsertCard() != GSM_TRUE)
{
if(++testCard >20)
{
printf("\r\n检测不到电话卡,请断电并重新接入电话卡\r\n");
}
GSM_DELAY(1000);
}
IsInsertCard()
同样的,有用的只有这一条
gsm_cmd("AT+CNUM\r","OK",200);
通过串口2发送"AT+CNUM\r", 然后等待200ms,然后判断接收的内容是不是"OK",是就返回正常(GSM_TRUE)
这时候GSM模块就已经初始化好了,下面可以发送消息了
/* 延时5秒再发送命令到模块 */
GSM_DELAY(5000);
//发送英文短信
if(gsm_sms((char *)num,"cxye") == GSM_TRUE)
printf("\r\n英文短信已发送至:%s,为方便测试,请在程序中修改接收短信的手机号码",num);
else
{
printf("\r\n短信发送失败,请确认目标号码有效");
}
GSM_DELAY(2000);
通过下面函数,发送"cxye" 查询余额
gsm_sms((char *)num,"cxye")
其中num是上面的 10086号码, "cxye"就是发送的内容
//生成电话号码命令
sprintf(cmdbuff,"AT+CMGS=\"%s\"\r",num);
将发送的电话号码10086,通过sprintf,复制到cmdbuff里面, 并且附加上短信头指令
然后把cxye内容复制到converbuff里面去
先发送电话号码 \\ sprintf(cmdbuff,"AT+CMGS=\"%s\"\r",num);
gsm_cmd(cmdbuff,">",200)
然后坐等回复一个>
再把信息通过
GSM_USART_printf("%s",converbuff);//发送短信内容
发送出去 (类似上图的This is a test 只是这里换成了cxye)
主循环
while(1)
{
GSM_DELAY(1000);
newmessadd=IsReceiveMS();
if(newmessadd)
{
IsRead=readmessage(newmessadd,namenum,str);
// printf("newmessadd=%d,IsRead:%d\n",newmessadd,IsRead);
if(IsRead)
{
printf("新短信\n\r");
hexuni2gbk(namenum,namegbk);
hexuni2gbk(str,gbkstr);
printf("新短信:\n发件人:%s\n内容:%s\n\r",namegbk,gbkstr);
}
}
}
newmessadd=IsReceiveMS();
查询是否接收到新短信
gsm_cmd_check("+CMTI:")
这个就是判断 有没有接收到 +CMTI: 字符串
找到回复信息的 内容首地址,通过strstr来匹配"+CMTI: \"SM\"
redata_off = strstr(redata,"+CMTI: \"SM\",");
主函数中的
IsRead=readmessage(newmessadd,namenum,str);
newmessadd为接收到回复信息的内容首地址
namenum为发送人(10086给你发送回信,这里发送人就是10086)
str 为10086给你发送的内容信息
sprintf(cmd,"AT+CMGR=%d\r",messadd);
先准备好字符内容cmd(通过sprintf,将AT+CMGR=内容地址,赋值给cmd的)
然后把要读取的信息头cmd发送出去, 然后坐等匹配到+CMGR:
匹配到之后 看看是不是首次读(UNREAD)
把发送人的手机号码提取出来(10086)
把日期,时间,和回复的内容都保存到str上面去
主函数中
hexuni2gbk功能为unicode与gbk互转功能
hexuni2gbk(namenum,namegbk); // 转换接受人姓名
hexuni2gbk(str,gbkstr); // 接收内容
最后把转好的内容通过printf打印到串口1上
printf("新短信:\n发件人:%s\n内容:%s\n\r",namegbk,gbkstr);
编译, 下载 看看
结果没有收到回信
开始调试程序
串口助手显示了下面
查一下CMGS:36, 只是说明已经发送成功了而已(现在发的是第36条),还是没接收到回信
现在问题是系统没有给我 自动上报接收到短信通知
不用32调试,直接用串口来发送AT命令看看
把串口1的短接帽拔下,拿来给GSM作USB转串口用
sTX->RXD ; sRx-> TXD, GND->GND
不需要程序,直接打开开关发命令就好
先发AT\r\n ,看看正常不
注意敲个回车
显示正常
检测是否插卡了, 显示也是正常
发短信试试
但还是没有收到新信息的命令
--------------------------------------------------------------------
2020年10月9日 昨天已经发现问题所在了,今天才有空写一写
1.AT+CNMI=?新消息指示 需要设置
设置为 AT+CNMI=2,1,0,0,0
就好,转自
https://blog.csdn.net/qq_35629563/article/details/82752886
2.问题调试出现再:短信只能存50条,多余50条就接受不了新消息了,只能删除
因此,我们要先查看信息
短信查看全部的,获取的数据要转码
AT+CMGL="ALL"
一般用上面语句,列出所有信息
删除具体某一条信息可以用
AT+CMGD=50
具体作用为删除第50条短信
也可以用AT+CMGDA="DEL READ"
作用为删除所有已读短信
3.当你再输入AT+CMGL="ALL" 列出所有信息时,如果还有空间容纳新短信(小于50条才能接受新内容,指示SIM900A是这样的),这时才能接受新的信息
比如你收到了一条信息, 它是下面的语句格式的(AT+CNMI=2,1,0,0,0设置情况下)
+CMTI: "SM",22
+CMTI就是标头, SM是指信息, 22是指的信息存储的位置
如果你要读22位置的短信,使用下面语句
AT+CMGR=32,0
作用为读取第32条消息,0指正常读
读完之后,22这位置的短信状态会由 REC UNREAD 变成 REC READ