一、环境介绍

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

//
//  功能描述   : 智能环境检测系统
//   时间      : 20190605
//   版本      : v3.3
//             版权所有,盗版必究。
//Copyright(C) DS小龙哥 2016 - 2020
///
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include <stdio.h>
#include "dht11.h"
#include "oled.h"
#include "adc.h"
#include "timer.h"
#include "sim800c.h"
#include "gps.h"/*
DTH11接线说明:
VCC---3.3V
GND---GND
DAT---PA5MQ-2接线说明:
VCC---3.3V
GND---GND
AO----PB0使用IIC接口的OLED显示屏接线说明:
GND---GND
VCC---3.3V
SDA---PB7
SCL---PB6使用SPI接口的OLED显示屏接线说明:
GND---GND
VCC---3.3V
D0-----PB5
D1-----PB6
RES----PB7
DC-----PB8
CS-----PB9  SIM800C接线说明:
GND----GND
PA2----SIM800C_RXD
PA3----SIM800C_TXDCH340模块接线说明:
GND----GND
RX-----PA9GPS接线说明: (波特率需要根据GPS模块实际情况进行修改)
GND----GND
VCC---3.3V
PB11----GPS_TX
*/u8 dht11_temp,dht11_humi;
u32 time_cnt=0;
u32 OneNet_Sendtime=0;
u8 data_select=0; //发送的数据选择
u8 DisplayState=0;
char DisplayDataBuffer[20];
u16 MQ_2; //存放ADC的数据
void DisplayPage1(void); //第一页
void DisplayPage2(void); //第二页//烟雾超标提示
u8 sim800c_buff[]="MQ-2 smoke exceeded";
char tmp_buffer[100];
double Longitude=103.718463; //经度
double latitude=36.107013;  //纬度int main(void)
{u8 state;USART_X_Init(USART1,72,115200); //串口初始化printf("串口初始化完成!\r\n");OLED_Init();         //OLED显示屏初始化ADC1_Init();if(DHT11_Init())printf("DHT11检测错误!\r\n");TIM2_Init(72,20000);//辅助串口3接收,超时时间为20msUSART_X_Init(USART2,36,9600); //可能的波特率(测试):  57600 、9600、115200USART_X_Init(USART3,36,9600);//接GPS模块TIM3_Init(72,20000);//辅助串口3接收,超时时间为20ms//显示初始化信息OLED_Clear_GRAM();OLED_DisplayString(0,0,16,"System Init..");OLED_Refresh_GRAM(); //刷新显存//延时等待printf("延时等待\r\n");DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);printf("开始初始化SIM800C \r\n");//初始化SIM800C  OLED_DisplayString(0,16,16,"SIM800C Init..");OLED_Refresh_GRAM(); //刷新显存while(1){state=SIM800C_InitCheck();if(state==0)break;DelayMs(1000);printf("SIM800C初始化状态:%d\r\n",state);}//设置文本模式OLED_DisplayString(0,32,16,"SIM800C Text Set...");OLED_Refresh_GRAM(); //刷新显存while(1){state=SIM800C_SetNoteTextMode();if(state==0)break;DelayMs(1000);printf("设置文本模式状态:%d\r\n",state);}//同步网络时间//SIM800C_NtpUpdate();//初始化GPRSSIM800C_GPRS_Init();while(1){delay_ms(1);time_cnt++;OneNet_Sendtime++;//记录时间if(time_cnt>=100){time_cnt=0;DisplayState=!DisplayState;printf("切换页面!\r\n");}//向云端发送一次数据(每次选择发送一种数据)if(OneNet_Sendtime>=500) //单位ms{OneNet_Sendtime=0;switch(data_select){case 0:OneNet_HTTP_DataUpdate("T",dht11_temp);break;case 1:OneNet_HTTP_DataUpdate("H",dht11_humi);break;case 2:OneNet_HTTP_DataUpdate("MQ2",MQ_2);break;case 3:OneNet_HTTP_GPS_DataUpdate("GPS",Longitude,latitude);break;}data_select++;if(data_select>3)data_select=0;}//采集DHT11温湿度与MQ-2的数据DHT11_Read_Data(&dht11_temp,&dht11_humi);MQ_2=ADC1_GetCHx(8);//串口打印数据
//       printf("温度:%d\r\n",dht11_temp);
//       printf("湿度:%d\r\n",dht11_humi);
//       printf("MQ-2:%d\r\n",MQ_2);//判断烟雾是否超标,设置阀值if(MQ_2>=2000){//发送短信if(SIM800C_SendNote((u8*)"13800138000",sim800c_buff,strlen((char*)sim800c_buff))==0)printf("短信发送成功\r\n");elseprintf("短信发送失败\r\n");}//采用时间间隔切换页面if(DisplayState){DisplayPage2();}else {DisplayPage1();}//实时接收WIFI收到的数据if(USART2_RX_FLAG){USART2_RX_BUFF[USART2_RX_CNT]='\0';USART2_RX_CNT=0;USART2_RX_FLAG=0;printf("USART2_RX_BUFF=%s\r\n",USART2_RX_BUFF);memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));}//实时接收GPS收到的数据if(USART3_RX_FLAG){USART3_RX_BUFF[USART3_RX_CNT]='\0';USART3_RX_CNT=0;USART3_RX_FLAG=0;//解析GPS经纬度信息GPS_GPRMC_Decoding(USART3_RX_BUFF,&Longitude,&latitude);printf("经度:%f,纬度:%f\r\n",Longitude,latitude);printf("USART2_RX_BUFF=%s\r\n",USART3_RX_BUFF);memset(USART2_RX_BUFF,0,sizeof(USART3_RX_BUFF));}}
}/*
函数功能:  温湿度DHT11显示页面
*/
void DisplayPage2(void)
{u8 i;OLED_Clear_GRAM();/*1. 最上方界面提示*/for(i=0;i<5;i++){OLED_DisplayData(24+i*16,0,16,16,ChineseFont[i+8]);  }/*2. 温湿度显示*/snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"T :%d",dht11_temp);OLED_DisplayString(40,24,16,DisplayDataBuffer);snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"RH:%d%%",dht11_humi);OLED_DisplayString(40,40,16,DisplayDataBuffer);OLED_Refresh_GRAM(); //刷新显存
}/*
函数功能:  烟雾传感器显示页面
*/
void DisplayPage1(void)
{u8 i;OLED_Clear_GRAM();/*1. 最上方界面提示*/for(i=0;i<6;i++){OLED_DisplayData(16+i*16,0,16,16,ChineseFont[i+13]); }/*2. 烟雾浓度显示*/snprintf(DisplayDataBuffer,sizeof(DisplayDataBuffer),"%d%%",MQ_2);OLED_DisplayString(40,24,16,DisplayDataBuffer);OLED_Refresh_GRAM(); //刷新显存
}

3.2 sim800c.c

#include "sim800c.h"/*
函数功能:向SIM800C模块发送指令
函数参数:char *cmd  发送的命令char *check_data 检测返回的数据
返回值: 0表示成功 1表示失败
*/
u8 SIM800C_SendCmd(char *cmd,char *check_data)
{u16 i,j;for(i=0;i<5;i++) //测试的总次数{USART2_RX_FLAG=0;USART2_RX_CNT=0;memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));USART_X_SendString(USART2,cmd); //发送指令for(j=0;j<500;j++) //等待的时间(ms单位){if(USART2_RX_FLAG){USART2_RX_BUFF[USART2_RX_CNT]='\0';if(strstr((char*)USART2_RX_BUFF,check_data)){return 0;}else break;}delay_ms(20); //一次的时间}}return 1;
}/*
函数  功能:GSM模块初始化检测
函数返回值:1表示模块检测失败,0表示成功
*/
u8 SIM800C_InitCheck(void)
{if(SIM800C_SendCmd("AT\r\n","OK"))return 1;else printf("SIM800模块正常!\r\n");if(SIM800C_SendCmd("ATE0\r\n","OK"))return 2;else printf("设置模块不回显成功!\r\n");if(SIM800C_SendCmd("AT+CGMI\r\n","OK"))return 3;else printf("查询制造商名称成功!%s\r\n",USART2_RX_BUFF);if(SIM800C_SendCmd("AT+CGMM\r\n","OK"))return 4;else printf("查询模块型号成功!%s\r\n",USART2_RX_BUFF);DelayMs(1000);DelayMs(1000);if(SIM800C_SendCmd("AT+CNUM\r\n","+CNUM:"))return 5;else printf("获取本机号码成功!%s\r\n",USART2_RX_BUFF);/* 返回格式如下:+CNUM: "","+8613086989413",145,7,4OK*/return 0;
}/*
函数  功能:GSM模块短信模式设置
函数返回值:0表示模块设置成功
*/
u8 SIM800C_SetNoteTextMode(void)
{if(SIM800C_SendCmd("AT+CSCS=\"GSM\"\r\n","OK"))return 1;// "GSM"字符集else printf("短信GSM字符集设置成功!\r\n");if(SIM800C_SendCmd("AT+CMGF=1\r\n","OK"))return 2; //文本模式else printf("短信文本模式设置成功!\r\n");return 0;
}/*
函数功能:发送短信
函数参数:num:电话号码text:短信内容
函数返回值:0表示发送成功
*/
u8 SIM800C_SendNote(u8 *num,u8 *text,u16 len)
{char data[50];char send_buf[2];sprintf(data,"AT+CMGS=\"%s\"\r\n",num);if(SIM800C_SendCmd(data,">"))return 1; //设置发送的手机号USART_X_SendData(USART2,text,len);     //发送短信内容send_buf[0] = 0x1a;send_buf[1] = '\0';if(SIM800C_SendCmd(send_buf,"+CMGS"))return 2; //发送结束符号return 0;
}/*
函数功能:NTP网络同步时间
*/
void SIM800C_NtpUpdate(void)
{  SIM800C_SendCmd("AT+SAPBR=3,1,\"Contype\",\"GPRS\"\r\n","OK");//配置承载场景1SIM800C_SendCmd("AT+SAPBR=3,1,\"APN\",\"CMNET\"\r\n","OK");SIM800C_SendCmd("AT+SAPBR=1,1\r\n","OK");                     //激活一个GPRS上下文DelayMs(5);SIM800C_SendCmd("AT+CNTPCID=1\r\n","OK");                     //设置CNTP使用的CIDSIM800C_SendCmd("AT+CNTP=\"202.120.2.101\",32\r\n","OK");     //设置NTP服务器和本地时区(32时区 时间最准确)SIM800C_SendCmd("AT+CNTP\r\n","+CNTP: 1");                    //同步网络时间printf("同步网络时间:%s\r\n",USART2_RX_BUFF);
}/*
函数功能:GPRS数据通信初始化
返 回 值: 0表示成功
*/
u8 SIM800C_GPRS_Init(void)
{SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK"); //关闭连接SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK");     //关闭移动场景 if(SIM800C_SendCmd("AT+CGCLASS=\"B\"\r\n","OK"))return 1;              //设置GPRS移动台类别为B,支持包交换和数据交换 if(SIM800C_SendCmd("AT+CGDCONT=1,\"IP\",\"CMNET\"\r\n","OK"))return 2;//设置PDP上下文,互联网接协议,接入点等信息if(SIM800C_SendCmd("AT+CGATT=1\r\n","OK"))return 3;                    //附着GPRS业务if(SIM800C_SendCmd("AT+CIPCSGP=1,\"CMNET\"\r\n","OK"))return 4;       //设置为GPRS连接模式if(SIM800C_SendCmd("AT+CIPHEAD=1\r\n","OK"))return 5;                    //设置接收数据显示IP头(方便判断数据来源)return 0;
}/*
函数功能: 连接TCP服务器
函数参数: ipaddr:ip地址port:端口
返 回 值: 0表示成功,其他值表示失败
*/
u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port)
{char cmd_buff[100];SIM800C_SendCmd("AT+CIPCLOSE=1\r\n","CLOSE OK");  //关闭连接SIM800C_SendCmd("AT+CIPSHUT\r\n","SHUT OK");     //关闭移动场景 sprintf(cmd_buff,"AT+CIPSTART=\"TCP\",\"%s\",\"%s\"\r\n",ipaddr,port);if(SIM800C_SendCmd(cmd_buff,"OK"))return 1;      //发起连接return 0;
}/*
函数功能: TCP客户端模式下发送数据
返 回 值: 0表示成功,其他值表示失败
*/
u8 SIIM800C_TCP_SendData(u8 *data,u32 len)
{char send_buf[2];//准备发送数据if(SIM800C_SendCmd("AT+CIPSEND\r\n",">")==0){//发送数据USART_X_SendData(USART2,data,len);//发送结束符号DelayMs(50);send_buf[0] = 0x1a;send_buf[1] = '\0';if(SIM800C_SendCmd(send_buf,"SEND OK"))return 2;else   return 0;}return 1;
}/*
函数功能: 采用HTTP协议方式向OneNet服务器上报数据
函数参数:char *data_point:数据点的名称u32 data :上传的数据
*/
char OneNet_HTTP_CMD[1024];
char OneNet_HTTP_BUFF[300];
#define ONENET_DEVICE_ID "529199894"
#define ONENET_API_KEY "GfYgLKD4UxsjgJqkXhEoYLhL6fE="void OneNet_HTTP_DataUpdate(char *data_point,u32 data)
{//拼接数据snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),"{\"datastreams\":[{\"id\":\"%s\",\"datapoints\":[{\"value\":%d}]}]}",data_point,data);//拼接数据snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),"POST /devices/%s/datapoints HTTP/1.1\r\n" \"api-key:%s\r\n" \"Host:api.heclouds.com\r\n" \"Connection:close\r\n" \"Content-Length:%d\r\n" \"\r\n" \"%s",ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF);printf("OneNet_HTTP_CMD=%s\r\n",OneNet_HTTP_CMD);printf("连接服务器的状态:%d\r\n",SIM800C_Connect_TCP_Server("183.230.40.33","80"));DelayMs(500);printf("数据发送的状态:%d\r\n",SIIM800C_TCP_SendData((u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD)));
}/*
函数功能: 采用HTTP协议方式向OneNet服务器上报GPS经纬度信息
函数参数:char *data_point:数据点的名称double Longitude,double latitude:上传的经纬度数据
*/
void OneNet_HTTP_GPS_DataUpdate(char *data_point,double Longitude,double latitude)
{//拼接数据snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),"{\"datastreams\":[{\"id\":\"%s\",\"datapoints\":[{\"value\":{\"lon\":%lf,\"lat\":%lf}}]}]}",data_point,Longitude,latitude);//拼接数据snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),"POST /devices/%s/datapoints HTTP/1.1\r\n" \"api-key:%s\r\n" \"Host:api.heclouds.com\r\n" \"Connection:close\r\n" \"Content-Length:%d\r\n" \"\r\n" \"%s",ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF);printf("GPS_OneNet_HTTP_CMD=%s\r\n",OneNet_HTTP_CMD);printf("连接服务器的状态:%d\r\n",SIM800C_Connect_TCP_Server("183.230.40.33","80"));DelayMs(500);printf("数据发送的状态:%d\r\n",SIIM800C_TCP_SendData((u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD)));
}

3.3 sim800c.h

#ifndef _GSM_H
#define _GSM_H
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"u8 SIM800C_SendCmd(char *cmd,char *check_data);
u8 SIM800C_InitCheck(void);
u8 SIM800C_SetNoteTextMode(void);
u8 SIM800C_SendNote(u8 *num,u8 *text,u16 len);
void SIM800C_NtpUpdate(void);
u8 SIM800C_GPRS_Init(void);
u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port);
u8 SIIM800C_TCP_SendData(u8 *data,u32 len);void OneNet_HTTP_GPS_DataUpdate(char *data_point,double Longitude,double latitude);
void OneNet_HTTP_DataUpdate(char *data_point,u32 data);
#endif

四、创建应用

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

STM32+SIM800C采用MQTT协议登录OneNet上传温湿度、MQ2烟雾浓度、GPS数据相关推荐

  1. STM32+移远MC20模块采用MQTT协议登录OneNet上传GPS数据

    一.环境介绍 MCU:  STM32F103C8T6 GSM模块: 移远MC20 (MT2503D)(GSM+GPS共存)功能很强大 开发软件: Keil5 MQTT协议采用OneNet的旧版协议,登 ...

  2. STM32+果云GA6-GPRS/GSM模块+MQTT+HTTP协议连接中移OneNet上传GPS数据定位

    一.环境介绍 MCU:  STM32F103C8T6 GSM模块: GA6--果云 开发软件: Keil5 完整源码下载:  https://download.csdn.net/download/xi ...

  3. 在鸿蒙开发板上使用MQTT协议、OneNET实现第一个物联网项目

    通常来说,一个物联网产品应当包括设备.云平台.手机APP.我将在鸿蒙系统上移植MQTT协议.OneNET接入协议,实现手机APP.网页两者都可以远程(跨网络,不是局域网的)访问开发板数据,并控制开发板 ...

  4. 中国移动物联网开放平台OneNET学习笔记(1)——设备接入(MQTT协议)OneNET Studio篇

    一.平台简介 中国移动物联网开放平台(OneNET) 是中移物联网有限公司基于物联网技术和产业特点打造的开放平台和生态环境,适配各种网络环境和协议类型,支持各类传感器和智能硬件的快速接入和大数据服务, ...

  5. micropython mqtt_MicroPython使用MQTT协议接入OneNET云平台

    MicroPython使用MQTT协议接入OneNET云平台 [复制链接] 本帖最后由 hanyeguxingwo 于 2016-11-22 11:33 编辑 之前使用Arduino+ESP8266使 ...

  6. CC3200使用MQTT协议连接Onenet平台实践

    代码仓库地址:https://github.com/idrey/CC3200_Onenet 0x01 介绍 CC3200是TI公司推出的一款WIFI MCU,支持多种网络协议.信息物理系统课程中使用的 ...

  7. 【stm32c8t6+esp8266上传温湿度到Onenet云平台】

    stm32c8t6+esp8266上传温湿度到Onenet云平台 最近做的一个小项目中需要将获取的数据到云平台,我选择的是onenet平台,下面会根据个人学习过程分享如何使用onenet平台以及如何通 ...

  8. 树莓派mqtt协议连接阿里云物联网平台,手机端获取数据并控制

    树莓派mqtt协议连接阿里云物联网平台(三) 前面树莓派的数据已经上传到云端,可是我的android手机该如何获取树莓派上传的这些数据呢,,困惑了我好几天的疑问,解开的那一刻,真的时拨开云雾见青天啊. ...

  9. Android实现注册登录头像上传等功能常规开发(Android端,服务器端开发实例)

    Android实现注册登录头像上传等功能常规开发(Android端,服务器端开发实例) 标签: 注册登录Android开发servlet 2017-04-18 20:34  454人阅读  评论(1) ...

  10. Android学习笔记---28_网络通信之通过HTTP协议实现文件上传,组拼http 的post方法,传输内容

    28_网络通信之通过HTTP协议实现文件上传 ---------------------------------------------- 1.注意,做表单提交的时候:程序代码;   <form ...

最新文章

  1. RedHat Enterprise 5.1下OpenLDAP的配置及PAMNSS的配置
  2. 如何用 OpenGL 绘制雪花?
  3. 程序员面对下列技术问题,如何做决策
  4. [Linux][Hadoop] 将hadoop跑起来
  5. css3个性loading,css3 中实现炫酷的loading效果
  6. mpvue微信小程序动画_入门微信小程序
  7. 新手指导:51CTO微博小技巧
  8. 《CLR via C#》读书笔记 之 基元类型、引用类型和值类型
  9. FocusLab新生大礼包三:Latex安装教程
  10. nginx:工作原理
  11. 生产环境 JDK6 升级 JDK8
  12. CFree5构建中止问题
  13. 便携计算机硬盘,科技:适用于Mac或PC的最佳便携式外置硬盘
  14. 以下是一段歌词,请从这段歌词中统计出朋友出现的次数
  15. 文本prompting综述
  16. 题解报告:hdu 1570 A C
  17. iPhone之随机数的生成
  18. OJ:剪子包袱锤游戏
  19. inotifywait+rsync同步
  20. 报错:使用java api连接redis集群时报错 READONLY You can't write against a read only slave.

热门文章

  1. 华为od python_华为运维开发-华为OD工资待遇怎么样 - 华为技术有限公司 - 职友集...
  2. 有负数c语言除法,C语言负数的除法和求余运算
  3. vm8.0下安装mac
  4. 通达信软件里php文件在哪,通达信股票交易软件使用秘籍
  5. Hinduja Global Solutions借助OpManager一年节省300万美元
  6. px和毫米的换算_px和厘米怎么换算?
  7. docker中DVWA的安装
  8. P-6002-10PK,P-6002-2PK脂质研究工具解析
  9. KEIL C51出现 runtime error R6002 floating point support not loaded解决办法
  10. 自回归模型 - PixelCNN