一、环境介绍
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---PA5
-
-
MQ-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_TXD
-
-
-
CH340模块接线说明:
-
GND----GND
-
RX-----PA9
-
-
GPS接线说明: (波特率需要根据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接收,超时时间为20ms
-
USART_X_Init(USART2,
36,
9600);
//可能的波特率(测试): 57600 、9600、115200
-
-
USART_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();
-
-
//初始化GPRS
-
SIM800C_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");
-
else
-
printf(
"短信发送失败\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,4
-
OK
-
*/
-
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");
//配置承载场景1
-
SIM800C_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使用的CID
-
SIM800C_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




转载:https://blog.csdn.net/xiaolong1126626497/article/details/116297671
查看评论