[STM32F1] sim868模块

[复制链接]
467|0
 楼主| kzlzqi 发表于 2023-5-26 14:29 | 显示全部楼层 |阅读模式
最近使用了SIM868模块做了项目,单片机使用的是STM32F103C8T6,使用串口2与SIM模块通信,实现了打电话、发短信、GPS定位、GPRS发送数据的功能,能够实时定位,1s发送一次定位数据到服务器。
SIM模块代码如下:
  1. #include "sim.h"
  2. #include "delay.h"
  3. #include "string.h"
  4. #include "oled.h"
  5. #include "key.h"
  6. #include "usart.h"
  7. #include "usart2.h"

  8. //SIM868 模块的响应格式为: <回车><换行><响应内容><回车><换行>。                                        !!!!!!!

  9. //发送的短信内容:SOS!我们在经纬度为39.915403,116.403906的地方遇险,请求帮助!
  10. unsigned char Send_Message[] = "0053004F0053002162114EEC57287ECF7EAC5EA64E3A00330039002E003900310035003400300033002C003100310036002E0034003000330039003000367684573065B990479669FF0C8BF76C425E2E52A9FF01";
  11. unsigned char LBS_Location[30] = {0};                        //保存基站定位最近一次读取到的位置信息
  12. unsigned char SNSS_Location[30] = {0};                //保存SNSS定位最近一次读取到的位置信息
  13. unsigned char IPaddr_port[] = "AT+CIPSTART="TCP","103.46.128.49","21455"";        //GPRS 连接的外网IP和端口号
  14. unsigned char GPRS_SEND[] = "ID001,39.915403,116.403906";                //GPRS 发送的信息。其中IDxxx为设备的编号,加上纬度,经度

  15. //发送命令后,检测接收到的应答
  16. //p:期待的应答结果
  17. //返回值:0,没有得到期待的应答结果
  18. //返回值:1,得到期待的应答结果
  19. #define SIM_Check_OK                1
  20. #define SIM_Check_ERROR        0
  21. unsigned char SIM_Check(unsigned char *p)
  22. {
  23.                 if(USART2_RX_STA&0X8000)                //判断串口是否接收到一次数据了
  24.                 {
  25.                                 USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;                //在接收到的字符最后添加结束符
  26.        
  27.                                 if(strstr((const char*)USART2_RX_BUF,(const char*)p) == NULL)                //判断 p 是否为 USART2_RX_BUF 的子串
  28.                                 {
  29.                                         //return 0;
  30.                                         return SIM_Check_ERROR;
  31.                                 }       
  32.                 }
  33.                
  34.                 //return 1;
  35.                 return SIM_Check_OK;
  36. }

  37. //向SIM800C发送命令
  38. //cmd:发送的命令字符串(不需要添加回车了)
  39. //ack:期待的应答结果,如果为空,则表示不需要等待应答
  40. //waittime:等待时间(单位:10ms)
  41. //返回值:0,发送成功(得到了期待的应答结果)
  42. //       1,发送失败
  43. #define SIM_Send_Cmd_OK                        0
  44. #define SIM_Send_Cmd_ERROR        1
  45. unsigned char SIM_Send_Cmd(u8 *cmd,u8 *ack,u16 waittime)
  46. {       
  47.                 unsigned char res = SIM_Send_Cmd_OK;
  48.        
  49.                 USART2_RX_STA=0;        //清空接收到的字符串数组
  50.                 if((u32)cmd<=0XFF)        //发送数字(如发短信的结束符0x1A)
  51.                 {
  52.                         while((USART2->SR&0X40)==0);        //等待上一次串口数据发送完成  
  53.                         USART2->DR=(u32)cmd;
  54.                 }
  55.                 else //发送命令
  56.                 {
  57.                         u2_printf("%s\r\n",cmd);//发送命令
  58.                 }

  59.                 if(ack&&waittime)          //需要等待应答
  60.                 {
  61.                          while(--waittime)  //等待倒计时
  62.                          {
  63.                                 delay_ms(10);
  64.                                 if(USART2_RX_STA&0X8000)//接收到期待的应答结果
  65.                                 {
  66.                                         if(SIM_Check(ack))        //判断SIM模块应答是否正常
  67.                                         {
  68.                                                 break;
  69.                                         }
  70.                                         USART2_RX_STA=0;
  71.                                 }
  72.                          }
  73.                          if(waittime==0)res=SIM_Send_Cmd_ERROR;                 //超时
  74.                 }
  75.        
  76.                 return res;
  77. }


  78. void SIM_Init()                                                //SIM卡初始化
  79. {       
  80.         unsigned char flag=1;
  81.        
  82.         while(SIM_Send_Cmd("AT","OK",100))                                        //检测是否应答AT指令
  83.         {               
  84.                         OLED_P8x16Str(0,1, "Sim Fail!");
  85.                         delay_ms(400);
  86.                         OLED_P8x16Str(0,1, "         ");
  87.                         delay_ms(300);
  88.         }
  89.         OLED_P8x16Str(0,1, "            ");       
  90.         OLED_P8x16Str(0,1, "AT is OK!");        
  91.        
  92.         SIM_Send_Cmd("ATE0","OK",100);//不回显
  93.         delay_ms(200);
  94.         while(SIM_Send_Cmd("AT+CPIN?","READY",100))        //检测是否存在SIM卡
  95.         {       
  96.                         OLED_P8x16Str(0,1, "No Sim Card!");
  97.                         delay_ms(400);
  98.                         OLED_P8x16Str(0,1, "            ");
  99.                         delay_ms(300);               
  100.         }
  101.         OLED_P8x16Str(0,1, "GPS Open...");
  102.         while(SIM_Send_Cmd("AT+CGNSPWR=1","OK",100))        //打开gps定位
  103.         {
  104.                         OLED_P8x16Str(0,1, "GPS Open fail!");
  105.                         delay_ms(400);
  106.                         OLED_P8x16Str(0,1, "              ");
  107.                         delay_ms(300);                       
  108.         }

  109.         OLED_P8x16Str(0,1, "GPRS Init...");
  110.         while(flag)                                                                                                                                                //设置GPRS通信
  111.         {
  112.                 flag = 0;
  113.                 SIM_Send_Cmd("AT+CIPCLOSE=1","ERROR",100);                //关闭当前 TCP 连接
  114.                 SIM_Send_Cmd("AT+CIPSHUT","OK",100);                                //关闭场景
  115.                
  116.                 if(SIM_Send_Cmd("AT+CGCLASS="B"","OK",1000))flag=1;                                                        //设置GPRS移动台类别为B,支持包交换和数据交换
  117.                 if(SIM_Send_Cmd("AT+CGDCONT=1,"IP","CMNET"","OK",1000))flag=2;        //设置PDP上下文,互联网接协议,接入点等信息
  118.                 if(SIM_Send_Cmd("AT+CGATT=1","OK",500))flag=3;                                                                                        //附着GPRS业务
  119.                 if(SIM_Send_Cmd("AT+CIPCSGP=1,"CMNET"","OK",500))flag=4;                                         //设置为GPRS连接模式
  120.                 if(SIM_Send_Cmd("AT+CIPHEAD=1","OK",500))flag=5;                                                                                 //设置接收数据显示IP头(方便判断数据来源)       

  121.                 if(flag)
  122.                 {
  123.                         OLED_P8x16Str(0,1, "GPRS ERROR!   ");
  124.                         delay_ms(800);
  125.                         OLED_P8x16Str(0,1, "              ");
  126.                         delay_ms(300);                                               
  127.                 }
  128.         }
  129.         while(SIM_Send_Cmd(IPaddr_port,"OK",500))                        //发起GPRS连接
  130.         {
  131.                         OLED_P8x16Str(0,1,"CONNECT FAIL!  ");
  132.                         delay_ms(400);
  133.                         OLED_P8x16Str(0,1, "              ");
  134.                         delay_ms(300);                       
  135.         }

  136.         OLED_P8x16Str(0,1, "              ");               
  137.         OLED_P8x16Str(0,1, "SIM is OK!");
  138.        
  139. }
  140. //函数功能:
  141. //1.不断读取定位信息,并且将有效的数据存储到GPRS_SEND数组中
  142. //2.将读取到的有效定位数据掉点保存(未实现)
  143. void SIM_ReadData()                //不断读取当前的定位信息
  144. {
  145.         //获取定位信息
  146.         if(SIM_Send_Cmd("AT+CGNSINF","+CGNSINF: 1,1",100) == SIM_Send_Cmd_OK)                        //定位数据有效则进行记录
  147.         {
  148.                 OLED_P6x8Str(0,5, "SNSS IS OK     ");        
  149.                 SNSS_Save_Location();                                //记录定位信息
  150.                 OLED_print(SNSS_Location);        //OLED显示定位信息
  151.                 Change_MessageLocation(SNSS_Location);        //修改发送的短信中的定位信息定位信息                       
  152.         }
  153.         else
  154.         {                                       
  155.                 OLED_P6x8Str(0,5, "GPS Location...");
  156.         }       
  157.        
  158. }

  159. //函数功能:
  160. //将数据发送到固定的端口中
  161. void SIM_GprsSend()
  162. {
  163.         if(SIM_Send_Cmd("AT+CIPSEND",">",500)==0)                //发送数据
  164.         {
  165.                 //printf("CIPSEND DATA:%s\r\n",p1);                                 //发送数据打印到串口
  166.                 u2_printf("%s\r\n",GPRS_SEND);
  167.                 delay_ms(50);
  168.                 if(SIM_Send_Cmd((u8*)0X1A,"SEND OK",1000)==0)
  169.                 {
  170.                         OLED_P6x8Str(0,3,"Data send is ok"); //最长等待10s
  171.                 }                       
  172.                 else
  173.                 {
  174.                         OLED_P6x8Str(0,3,"Data send is error");
  175.                 }
  176.                 delay_ms(500);
  177.                 OLED_P8x16Str(0,3,"                  ");       
  178.         }
  179.         else
  180.         {
  181.                 SIM_Send_Cmd((u8*)0X1B,0,0);        //ESC,取消发送                
  182.         }                       
  183.        
  184. }


  185. void SIM_SendMessage()    //发短信        OK
  186. {
  187.         OLED_P8x16Str(0,5, "                ");                        
  188.         OLED_P8x16Str(0,5, "Send a Message..");        
  189.        
  190.         SIM_Send_Cmd("AT","OK",100);       
  191.         SIM_Send_Cmd("AT+CMGF=1","OK",100);                //设置短信模式为文本模式
  192.         SIM_Send_Cmd("AT+CSMP=17,167,1,8","OK",100);                //设置短信为中英文模式
  193.         SIM_Send_Cmd("AT+CSCS="UCS2"","OK",100);                //设置为UCS2字符集编码
  194.         SIM_Send_Cmd("AT+CMGS="0031 0033 003x003x003x003x003x003x003x003x003x"",">",500);                //设置对方手机号,需要修改
  195.         SIM_Send_Cmd(Send_Message,">",1000);                //发送短信内容
  196.        
  197.         SIM_Send_Cmd((u8*)0X1A,"+CMGS:",1000);//发送结束符,等待发送完成(最长等待10秒钟,因为短信长了的话,等待时间会长一些)       
  198.                
  199.         OLED_P8x16Str(0,5, "Finish Send!    ");
  200.         delay_ms(500);
  201.         OLED_P8x16Str(0,5, "                ");                
  202. }

  203. void SIM_Call()                                                //打电话                OK
  204. {
  205.                 unsigned char Key;
  206.                 unsigned char callbuf[] = "13xxxxxxxxx;";                //预存电话,需要修改

  207.                 OLED_P8x16Str(0,5, "               ");                        
  208.                 OLED_P8x16Str(0,5, "Call a phone...");
  209.        
  210.                 u2_printf("ATD%s\r\n",callbuf);                //拨号
  211.        
  212.                 while(1)
  213.                 {
  214.                         Key = KEY_Scan(0);
  215.                         if(Key == KEY2_PRES)
  216.                         {
  217.                                 u2_printf("ATH\r\n");        //挂电话       
  218.                                 OLED_P8x16Str(0,5, "over the phone!");
  219.                                 delay_ms(500);
  220.                                 OLED_P8x16Str(0,5, "               ");
  221.                                 break;
  222.                         }
  223.                 }       
  224. }                       

  225. //根据模块的基站定位和SNSS定位修改发送的信息和GPRS发送的消息的经纬度
  226. //参数: *p       
  227. //LBS_Location表示使用的是基站定位
  228. //SNSS_Location表示的是使用SNSS定位
  229. void Change_MessageLocation(unsigned char p[])
  230. {
  231.         unsigned char i;
  232.        
  233.         for(i=12; i<32; i++)        //修改报警信息中的经纬度
  234.         {
  235.                         if((i==15)||(i==22)||(i==25))        //小数点不修改
  236.                         {
  237.                                 continue;
  238.                         }
  239.                        
  240.                         Send_Message[i*4-1] = p[i-12];
  241.                
  242.         }
  243.        
  244.         for(i=0; i<20; i++)        //修改GPRS发送的经纬度
  245.         {
  246.                 GPRS_SEND[i+6] = p[i];
  247.         }
  248.        
  249. }

  250. void LBS_Save_Location()                //保存基站定位最近一次的位置信息, 基站定位是输出 精度,纬度
  251. {
  252.         unsigned char i,flag = 0;
  253.        
  254.         if((USART2_RX_BUF[2] == '+')&&(USART2_RX_BUF[9] == '0'))                //判断SIM模块是否读取到了地址
  255.         {
  256.                 for(i=11; flag != 2; i++)                //SIM模块LBS定位返回来的信息,第11位开始为经纬度信息。注意sim868返回消息的格式
  257.                 {
  258.                         if(USART2_RX_BUF[i] == ',')
  259.                         {
  260.                                         flag++;
  261.                         }
  262.                         LBS_Location[i-11] = USART2_RX_BUF[i];        //记录经纬度
  263.                 }
  264.                
  265.                 LBS_Location[i-12] = '\0';                //添加结束符
  266.         }
  267. }

  268. void OLED_print(unsigned char p[])                //基站定位和SNSS定位显示经纬度到OLED
  269. {
  270.                 unsigned char i,Flag = 0;
  271.                 for(i=0;p[i] != '\0';i++)
  272.                 {
  273.                         if(p[i] == ',')        //分开经度和纬度
  274.                         {
  275.                                         p[i] = 0;       
  276.                                         Flag = i;
  277.                                         break;
  278.                         }                       
  279.                 }
  280.                
  281.                 if(Flag != 0)
  282.                 {
  283.                                 OLED_P6x8Str(0,6,p);
  284.                                 OLED_P6x8Str(0,7,p+i+1);
  285.                                 p[i] = ',';       
  286.                 }
  287. }

  288. void SNSS_Save_Location()                //保存SNSS定位最近一次的位置信息,SNSS定位输出是 纬度,经度
  289. {
  290.         unsigned char i,flag = 0;
  291.        
  292.         for(i=35; flag != 2; i++)                //SIM模块SNSS定位返回来的信息,第35位开始为经纬度信息。注意sim868返回消息的格式
  293.         {
  294.                 if(USART2_RX_BUF[i] == ',')
  295.                 {
  296.                                 flag++;
  297.                 }
  298.                 SNSS_Location[i-35] = USART2_RX_BUF[i];        //记录经纬度
  299.         }
  300.        
  301.         SNSS_Location[i-36] = '\0';                //添加结束符
  302.        
  303. }




您需要登录后才可以回帖 登录 | 注册

本版积分规则

127

主题

996

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部