当前位置:   article > 正文

STM32+SIM800C采用MQTT协议登录OneNet上传温湿度、MQ2烟雾浓度、GPS数据_mq137测模块stm32代码

mq137测模块stm32代码

一、环境介绍

MCU:  STM32F103C8T6

GSM模块: SIM800C

开发软件: Keil5

MQTT协议采用OneNet的旧版协议,登录OneNet控制台创建应用时要选择旧版本。

如果想使用新版本的标准MQTT协议连接OnetNet请参考这里:  https://blog.csdn.net/xiaolong1126626497/article/details/107385118

完整源代码下载:  https://download.csdn.net/download/xiaolong1126626497/18245757

二、硬件与需求

一块STM32F103C8T6最小系统板。

                                                               

一块OLED显示屏

一个DHT11温湿度传感器 

一个MQ-2可燃气体传感器 

一个SIM800C模块 

 软件要求

采集DHT11温度、湿度数据、采集MQ-2烟雾传感器数据实时在OLED显示屏上显示、当烟雾浓度超过阀值时,可以通过SIM800C向指定手机号码发送短信。

并需要使用SIM800C连接GPRS网络,将温度、湿度、烟雾浓度上传到OneNet服务器进行可视化显示。

 

三、核心代码

3.1  main.c

  1. //
  2. // 功能描述 : 智能环境检测系统
  3. // 时间 : 20190605
  4. // 版本 : v3.3
  5. // 版权所有,盗版必究。
  6. //Copyright(C) DS小龙哥 2016 - 2020
  7. ///
  8. #include "stm32f10x.h"
  9. #include "delay.h"
  10. #include "usart.h"
  11. #include <stdio.h>
  12. #include "dht11.h"
  13. #include "oled.h"
  14. #include "adc.h"
  15. #include "timer.h"
  16. #include "sim800c.h"
  17. #include "gps.h"
  18. /*
  19. DTH11接线说明:
  20. VCC---3.3V
  21. GND---GND
  22. DAT---PA5
  23. MQ-2接线说明:
  24. VCC---3.3V
  25. GND---GND
  26. AO----PB0
  27. 使用IIC接口的OLED显示屏接线说明:
  28. GND---GND
  29. VCC---3.3V
  30. SDA---PB7
  31. SCL---PB6
  32. 使用SPI接口的OLED显示屏接线说明:
  33. GND---GND
  34. VCC---3.3V
  35. D0-----PB5
  36. D1-----PB6
  37. RES----PB7
  38. DC-----PB8
  39. CS-----PB9
  40. SIM800C接线说明:
  41. GND----GND
  42. PA2----SIM800C_RXD
  43. PA3----SIM800C_TXD
  44. CH340模块接线说明:
  45. GND----GND
  46. RX-----PA9
  47. GPS接线说明: (波特率需要根据GPS模块实际情况进行修改)
  48. GND----GND
  49. VCC---3.3V
  50. PB11----GPS_TX
  51. */
  52. u8 dht11_temp,dht11_humi;
  53. u32 time_cnt=0;
  54. u32 OneNet_Sendtime=0;
  55. u8 data_select=0; //发送的数据选择
  56. u8 DisplayState=0;
  57. char DisplayDataBuffer[20];
  58. u16 MQ_2; //存放ADC的数据
  59. void DisplayPage1(void); //第一页
  60. void DisplayPage2(void); //第二页
  61. //烟雾超标提示
  62. u8 sim800c_buff[]="MQ-2 smoke exceeded";
  63. char tmp_buffer[100];
  64. double Longitude=103.718463; //经度
  65. double latitude=36.107013; //纬度
  66. int main(void)
  67. {
  68. u8 state;
  69. USART_X_Init(USART1,72,115200); //串口初始化
  70. printf("串口初始化完成!\r\n");
  71. OLED_Init(); //OLED显示屏初始化
  72. ADC1_Init();
  73. if(DHT11_Init())printf("DHT11检测错误!\r\n");
  74. TIM2_Init(72,20000);//辅助串口3接收,超时时间为20ms
  75. USART_X_Init(USART2,36,9600); //可能的波特率(测试): 57600 、9600、115200
  76. USART_X_Init(USART3,36,9600);//接GPS模块
  77. TIM3_Init(72,20000);//辅助串口3接收,超时时间为20ms
  78. //显示初始化信息
  79. OLED_Clear_GRAM();
  80. OLED_DisplayString(0,0,16,"System Init..");
  81. OLED_Refresh_GRAM(); //刷新显存
  82. //延时等待
  83. printf("延时等待\r\n");
  84. DelayMs(1000);
  85. DelayMs(1000);
  86. DelayMs(1000);
  87. DelayMs(1000);
  88. printf("开始初始化SIM800C \r\n");
  89. //初始化SIM800C
  90. OLED_DisplayString(0,16,16,"SIM800C Init..");
  91. OLED_Refresh_GRAM(); //刷新显存
  92. while(1)
  93. {
  94. state=SIM800C_InitCheck();
  95. if(state==0)break;
  96. DelayMs(1000);
  97. printf("SIM800C初始化状态:%d\r\n",state);
  98. }
  99. //设置文本模式
  100. OLED_DisplayString(0,32,16,"SIM800C Text Set...");
  101. OLED_Refresh_GRAM(); //刷新显存
  102. while(1)
  103. {
  104. state=SIM800C_SetNoteTextMode();
  105. if(state==0)break;
  106. DelayMs(1000);
  107. printf("设置文本模式状态:%d\r\n",state);
  108. }
  109. //同步网络时间
  110. //SIM800C_NtpUpdate();
  111. //初始化GPRS
  112. SIM800C_GPRS_Init();
  113. while(1)
  114. {
  115. delay_ms(1);
  116. time_cnt++;
  117. OneNet_Sendtime++;
  118. //记录时间
  119. if(time_cnt>=100)
  120. {
  121. time_cnt=0;
  122. DisplayState=!DisplayState;
  123. printf("切换页面!\r\n");
  124. }
  125. //向云端发送一次数据(每次选择发送一种数据)
  126. if(OneNet_Sendtime>=500) //单位ms
  127. {
  128. OneNet_Sendtime=0;
  129. switch(data_select)
  130. {
  131. case 0:OneNet_HTTP_DataUpdate("T",dht11_temp);
  132. break;
  133. case 1:OneNet_HTTP_DataUpdate("H",dht11_humi);
  134. break;
  135. case 2:OneNet_HTTP_DataUpdate("MQ2",MQ_2);
  136. break;
  137. case 3:OneNet_HTTP_GPS_DataUpdate("GPS",Longitude,latitude);
  138. break;
  139. }
  140. data_select++;
  141. if(data_select>3)data_select=0;
  142. }
  143. //采集DHT11温湿度与MQ-2的数据
  144. DHT11_Read_Data(&dht11_temp,&dht11_humi);
  145. MQ_2=ADC1_GetCHx(8);
  146. //串口打印数据
  147. // printf("温度:%d\r\n",dht11_temp);
  148. // printf("湿度:%d\r\n",dht11_humi);
  149. // printf("MQ-2:%d\r\n",MQ_2);
  150. //判断烟雾是否超标,设置阀值
  151. if(MQ_2>=2000)
  152. {
  153. //发送短信
  154. if(SIM800C_SendNote((u8*)"13800138000",sim800c_buff,strlen((char*)sim800c_buff))==0)
  155. printf("短信发送成功\r\n");
  156. else
  157. printf("短信发送失败\r\n");
  158. }
  159. //采用时间间隔切换页面
  160. if(DisplayState)
  161. {
  162. DisplayPage2();
  163. }
  164. else
  165. {
  166. DisplayPage1();
  167. }
  168. //实时接收WIFI收到的数据
  169. if(USART2_RX_FLAG)
  170. {
  171. USART2_RX_BUFF[USART2_RX_CNT]='\0';
  172. USART2_RX_CNT=0;
  173. USART2_RX_FLAG=0;
  174. printf("USART2_RX_BUFF=%s\r\n",USART2_RX_BUFF);
  175. memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
  176. }
  177. //实时接收GPS收到的数据
  178. if(USART3_RX_FLAG)
  179. {
  180. USART3_RX_BUFF[USART3_RX_CNT]='\0';
  181. USART3_RX_CNT=0;
  182. USART3_RX_FLAG=0;
  183. //解析GPS经纬度信息
  184. GPS_GPRMC_Decoding(USART3_RX_BUFF,&Longitude,&latitude);
  185. printf("经度:%f,纬度:%f\r\n",Longitude,latitude);
  186. printf("USART2_RX_BUFF=%s\r\n",USART3_RX_BUFF);
  187. memset(USART2_RX_BUFF,0,sizeof(USART3_RX_BUFF));
  188. }
  189. }
  190. }
  191. /*
  192. 函数功能: 温湿度DHT11显示页面
  193. */
  194. void DisplayPage2(void)
  195. {
  196. u8 i;
  197. OLED_Clear_GRAM();
  198. /*1. 最上方界面提示*/
  199. for(i=0;i<5;i++)
  200. {
  201. OLED_DisplayData(24+i*16,0,16,16,ChineseFont[i+8]);
  202. }
  203. /*2. 温湿度显示*/
  204. snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"T :%d",dht11_temp);
  205. OLED_DisplayString(40,24,16,DisplayDataBuffer);
  206. snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"RH:%d%%",dht11_humi);
  207. OLED_DisplayString(40,40,16,DisplayDataBuffer);
  208. OLED_Refresh_GRAM(); //刷新显存
  209. }
  210. /*
  211. 函数功能: 烟雾传感器显示页面
  212. */
  213. void DisplayPage1(void)
  214. {
  215. u8 i;
  216. OLED_Clear_GRAM();
  217. /*1. 最上方界面提示*/
  218. for(i=0;i<6;i++)
  219. {
  220. OLED_DisplayData(16+i*16,0,16,16,ChineseFont[i+13]);
  221. }
  222. /*2. 烟雾浓度显示*/
  223. snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"%d%%",MQ_2);
  224. OLED_DisplayString(40,24,16,DisplayDataBuffer);
  225. OLED_Refresh_GRAM(); //刷新显存
  226. }

3.2 sim800c.c

  1. #include "sim800c.h"
  2. /*
  3. 函数功能:向SIM800C模块发送指令
  4. 函数参数:
  5. char *cmd 发送的命令
  6. char *check_data 检测返回的数据
  7. 返回值: 0表示成功 1表示失败
  8. */
  9. u8 SIM800C_SendCmd(char *cmd,char *check_data)
  10. {
  11. u16 i,j;
  12. for(i=0;i<5;i++) //测试的总次数
  13. {
  14. USART2_RX_FLAG=0;
  15. USART2_RX_CNT=0;
  16. memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
  17. USART_X_SendString(USART2,cmd); //发送指令
  18. for(j=0;j<500;j++) //等待的时间(ms单位)
  19. {
  20. if(USART2_RX_FLAG)
  21. {
  22. USART2_RX_BUFF[USART2_RX_CNT]='\0';
  23. if(strstr((char*)USART2_RX_BUFF,check_data))
  24. {
  25. return 0;
  26. }
  27. else break;
  28. }
  29. delay_ms(20); //一次的时间
  30. }
  31. }
  32. return 1;
  33. }
  34. /*
  35. 函数 功能:GSM模块初始化检测
  36. 函数返回值:1表示模块检测失败,0表示成功
  37. */
  38. u8 SIM800C_InitCheck(void)
  39. {
  40. if(SIM800C_SendCmd("AT\r\n","OK"))return 1;
  41. else printf("SIM800模块正常!\r\n");
  42. if(SIM800C_SendCmd("ATE0\r\n","OK"))return 2;
  43. else printf("设置模块不回显成功!\r\n");
  44. if(SIM800C_SendCmd("AT+CGMI\r\n","OK"))return 3;
  45. else printf("查询制造商名称成功!%s\r\n",USART2_RX_BUFF);
  46. if(SIM800C_SendCmd("AT+CGMM\r\n","OK"))return 4;
  47. else printf("查询模块型号成功!%s\r\n",USART2_RX_BUFF);
  48. DelayMs(1000);
  49. DelayMs(1000);
  50. if(SIM800C_SendCmd("AT+CNUM\r\n","+CNUM:"))return 5;
  51. else printf("获取本机号码成功!%s\r\n",USART2_RX_BUFF);
  52. /* 返回格式如下:
  53. +CNUM: "","+8613086989413",145,7,4
  54. OK
  55. */
  56. return 0;
  57. }
  58. /*
  59. 函数 功能:GSM模块短信模式设置
  60. 函数返回值:0表示模块设置成功
  61. */
  62. u8 SIM800C_SetNoteTextMode(void)
  63. {
  64. if(SIM800C_SendCmd("AT+CSCS=\"GSM\"\r\n","OK"))return 1;// "GSM"字符集
  65. else printf("短信GSM字符集设置成功!\r\n");
  66. if(SIM800C_SendCmd("AT+CMGF=1\r\n","OK"))return 2; //文本模式
  67. else printf("短信文本模式设置成功!\r\n");
  68. return 0;
  69. }
  70. /*
  71. 函数功能:发送短信
  72. 函数参数:
  73. num:电话号码
  74. text:短信内容
  75. 函数返回值:0表示发送成功
  76. */
  77. u8 SIM800C_SendNote(u8 *num,u8 *text,u16 len)
  78. {
  79. char data[50];
  80. char send_buf[2];
  81. sprintf(data,"AT+CMGS=\"%s\"\r\n",num);
  82. if(SIM800C_SendCmd(data,">"))return 1; //设置发送的手机号
  83. USART_X_SendData(USART2,text,len); //发送短信内容
  84. send_buf[0] = 0x1a;
  85. send_buf[1] = '\0';
  86. if(SIM800C_SendCmd(send_buf,"+CMGS"))return 2; //发送结束符号
  87. return 0;
  88. }
  89. /*
  90. 函数功能:NTP网络同步时间
  91. */
  92. void SIM800C_NtpUpdate(void)
  93. {
  94. SIM800C_SendCmd("AT+SAPBR=3,1,\"Contype\",\"GPRS\"\r\n","OK");//配置承载场景1
  95. SIM800C_SendCmd("AT+SAPBR=3,1,\"APN\",\"CMNET\"\r\n","OK");
  96. SIM800C_SendCmd("AT+SAPBR=1,1\r\n","OK"); //激活一个GPRS上下文
  97. DelayMs(5);
  98. SIM800C_SendCmd("AT+CNTPCID=1\r\n","OK"); //设置CNTP使用的CID
  99. SIM800C_SendCmd("AT+CNTP=\"202.120.2.101\",32\r\n","OK"); //设置NTP服务器和本地时区(32时区 时间最准确)
  100. SIM800C_SendCmd("AT+CNTP\r\n","+CNTP: 1"); //同步网络时间
  101. printf("同步网络时间:%s\r\n",USART2_RX_BUFF);
  102. }
  103. /*
  104. 函数功能:GPRS数据通信初始化
  105. 返 回 值: 0表示成功
  106. */
  107. u8 SIM800C_GPRS_Init(void)
  108. {
  109. SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK"); //关闭连接
  110. SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK"); //关闭移动场景
  111. if(SIM800C_SendCmd("AT+CGCLASS=\"B\"\r\n","OK"))return 1; //设置GPRS移动台类别为B,支持包交换和数据交换
  112. if(SIM800C_SendCmd("AT+CGDCONT=1,\"IP\",\"CMNET\"\r\n","OK"))return 2;//设置PDP上下文,互联网接协议,接入点等信息
  113. if(SIM800C_SendCmd("AT+CGATT=1\r\n","OK"))return 3; //附着GPRS业务
  114. if(SIM800C_SendCmd("AT+CIPCSGP=1,\"CMNET\"\r\n","OK"))return 4; //设置为GPRS连接模式
  115. if(SIM800C_SendCmd("AT+CIPHEAD=1\r\n","OK"))return 5; //设置接收数据显示IP头(方便判断数据来源)
  116. return 0;
  117. }
  118. /*
  119. 函数功能: 连接TCP服务器
  120. 函数参数:
  121. ipaddr:ip地址
  122. port:端口
  123. 返 回 值: 0表示成功,其他值表示失败
  124. */
  125. u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port)
  126. {
  127. char cmd_buff[100];
  128. SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK"); //关闭连接
  129. SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK"); //关闭移动场景
  130. sprintf(cmd_buff,"AT+CIPSTART=\"TCP\",\"%s\",\"%s\"\r\n",ipaddr,port);
  131. if(SIM800C_SendCmd(cmd_buff,"OK"))return 1; //发起连接
  132. return 0;
  133. }
  134. /*
  135. 函数功能: TCP客户端模式下发送数据
  136. 返 回 值: 0表示成功,其他值表示失败
  137. */
  138. u8 SIIM800C_TCP_SendData(u8 *data,u32 len)
  139. {
  140. char send_buf[2];
  141. //准备发送数据
  142. if(SIM800C_SendCmd("AT+CIPSEND\r\n",">")==0)
  143. {
  144. //发送数据
  145. USART_X_SendData(USART2,data,len);
  146. //发送结束符号
  147. DelayMs(50);
  148. send_buf[0] = 0x1a;
  149. send_buf[1] = '\0';
  150. if(SIM800C_SendCmd(send_buf,"SEND OK"))return 2;
  151. else return 0;
  152. }
  153. return 1;
  154. }
  155. /*
  156. 函数功能: 采用HTTP协议方式向OneNet服务器上报数据
  157. 函数参数:
  158. char *data_point:数据点的名称
  159. u32 data :上传的数据
  160. */
  161. char OneNet_HTTP_CMD[1024];
  162. char OneNet_HTTP_BUFF[300];
  163. #define ONENET_DEVICE_ID "529199894"
  164. #define ONENET_API_KEY "GfYgLKD4UxsjgJqkXhEoYLhL6fE="
  165. void OneNet_HTTP_DataUpdate(char *data_point,u32 data)
  166. {
  167. //拼接数据
  168. snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),
  169. "{\"datastreams\":[{\"id\":\"%s\",\"datapoints\":[{\"value\":%d}]}]}",data_point,data);
  170. //拼接数据
  171. snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),
  172. "POST /devices/%s/datapoints HTTP/1.1\r\n" \
  173. "api-key:%s\r\n" \
  174. "Host:api.heclouds.com\r\n" \
  175. "Connection:close\r\n" \
  176. "Content-Length:%d\r\n" \
  177. "\r\n" \
  178. "%s",
  179. ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF
  180. );
  181. printf("OneNet_HTTP_CMD=%s\r\n",OneNet_HTTP_CMD);
  182. printf("连接服务器的状态:%d\r\n",SIM800C_Connect_TCP_Server("183.230.40.33","80"));
  183. DelayMs(500);
  184. printf("数据发送的状态:%d\r\n",SIIM800C_TCP_SendData((u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD)));
  185. }
  186. /*
  187. 函数功能: 采用HTTP协议方式向OneNet服务器上报GPS经纬度信息
  188. 函数参数:
  189. char *data_point:数据点的名称
  190. double Longitude,double latitude:上传的经纬度数据
  191. */
  192. void OneNet_HTTP_GPS_DataUpdate(char *data_point,double Longitude,double latitude)
  193. {
  194. //拼接数据
  195. snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),
  196. "{\"datastreams\":[{\"id\":\"%s\",\"datapoints\":[{\"value\":{\"lon\":%lf,\"lat\":%lf}}]}]}",
  197. data_point,Longitude,latitude);
  198. //拼接数据
  199. snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),
  200. "POST /devices/%s/datapoints HTTP/1.1\r\n" \
  201. "api-key:%s\r\n" \
  202. "Host:api.heclouds.com\r\n" \
  203. "Connection:close\r\n" \
  204. "Content-Length:%d\r\n" \
  205. "\r\n" \
  206. "%s",
  207. ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF
  208. );
  209. printf("GPS_OneNet_HTTP_CMD=%s\r\n",OneNet_HTTP_CMD);
  210. printf("连接服务器的状态:%d\r\n",SIM800C_Connect_TCP_Server("183.230.40.33","80"));
  211. DelayMs(500);
  212. printf("数据发送的状态:%d\r\n",SIIM800C_TCP_SendData((u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD)));
  213. }

3.3 sim800c.h

  1. #ifndef _GSM_H
  2. #define _GSM_H
  3. #include "stm32f10x.h"
  4. #include "usart.h"
  5. #include "delay.h"
  6. u8 SIM800C_SendCmd(char *cmd,char *check_data);
  7. u8 SIM800C_InitCheck(void);
  8. u8 SIM800C_SetNoteTextMode(void);
  9. u8 SIM800C_SendNote(u8 *num,u8 *text,u16 len);
  10. void SIM800C_NtpUpdate(void);
  11. u8 SIM800C_GPRS_Init(void);
  12. u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port);
  13. u8 SIIM800C_TCP_SendData(u8 *data,u32 len);
  14. void OneNet_HTTP_GPS_DataUpdate(char *data_point,double Longitude,double latitude);
  15. void OneNet_HTTP_DataUpdate(char *data_point,u32 data);
  16. #endif

四、创建应用

发布的链接:  https://open.iot.10086.cn/iotbox/appsquare/appview?openid=6b5f9941b4d0464671fa1bb6cd3511dc

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/381561
推荐阅读
相关标签
  

闽ICP备14008679号