• 方案介紹
    • 一、環(huán)境介紹
    • 二、硬件與需求
    • 三、核心代碼
    • 四、創(chuàng)建應(yīng)用
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

STM32+SIM800C采用MQTT協(xié)議登錄OneNet上傳溫濕度、MQ2煙霧濃度、GPS數(shù)據(jù)

01/28 08:48
3162
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請(qǐng)聯(lián)系.docx

共1個(gè)文件

一、環(huán)境介紹

MCU:??STM32F103C8T6

GSM模塊:?SIM800C

開(kāi)發(fā)軟件:?Keil5

MQTT協(xié)議采用OneNet的舊版協(xié)議,登錄OneNet控制臺(tái)創(chuàng)建應(yīng)用時(shí)要選擇舊版本。

如果想使用新版本的標(biāo)準(zhǔn)MQTT協(xié)議連接OnetNet請(qǐng)參考這里:
https://blog.csdn.net/xiaolong1126626497/article/details/107385118

完整源代碼下載:?
https://download.csdn.net/download/xiaolong1126626497/18245757

二、硬件與需求

一塊STM32F103C8T6最小系統(tǒng)板。

一塊OLED顯示屏

一個(gè)DHT11溫濕度傳感器?

一個(gè)MQ-2可燃?xì)怏w傳感器?

一個(gè)SIM800C模塊?

?軟件要求

采集DHT11溫度、濕度數(shù)據(jù)、采集MQ-2煙霧傳感器數(shù)據(jù)實(shí)時(shí)在OLED顯示屏上顯示、當(dāng)煙霧濃度超過(guò)閥值時(shí),可以通過(guò)SIM800C向指定手機(jī)號(hào)碼發(fā)送短信。

并需要使用SIM800C連接GPRS網(wǎng)絡(luò),將溫度、濕度、煙霧濃度上傳到OneNet服務(wù)器進(jìn)行可視化顯示。

三、核心代碼

3.1? main.c

//	 
//  功能描述   : 智能環(huán)境檢測(cè)系統(tǒng)
//   時(shí)間      : 20190605
//   版本      : v3.3
//             版權(quán)所有,盜版必究。
//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接線說(shuō)明:
VCC---3.3V
GND---GND
DAT---PA5

MQ-2接線說(shuō)明:
VCC---3.3V
GND---GND
AO----PB0

使用IIC接口的OLED顯示屏接線說(shuō)明:
GND---GND
VCC---3.3V
SDA---PB7
SCL---PB6

使用SPI接口的OLED顯示屏接線說(shuō)明:
GND---GND
VCC---3.3V
D0-----PB5
D1-----PB6
RES----PB7
DC-----PB8
CS-----PB9  

SIM800C接線說(shuō)明:
GND----GND
PA2----SIM800C_RXD
PA3----SIM800C_TXD


CH340模塊接線說(shuō)明:
GND----GND
RX-----PA9

GPS接線說(shuō)明: (波特率需要根據(jù)GPS模塊實(shí)際情況進(jìn)行修改)
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; //發(fā)送的數(shù)據(jù)選擇
u8 DisplayState=0;
char DisplayDataBuffer[20];
u16 MQ_2; //存放ADC的數(shù)據(jù)
void DisplayPage1(void); //第一頁(yè)
void DisplayPage2(void); //第二頁(yè)

//煙霧超標(biāo)提示
u8 sim800c_buff[]="MQ-2 smoke exceeded";
char tmp_buffer[100];
double Longitude=103.718463; //經(jīng)度
double latitude=36.107013;  //緯度

int main(void)
{
	u8 state;
	USART_X_Init(USART1,72,115200); //串口初始化
	printf("串口初始化完成!rn");
	OLED_Init();         //OLED顯示屏初始化
  ADC1_Init();
	if(DHT11_Init())printf("DHT11檢測(cè)錯(cuò)誤!rn");
	
	TIM2_Init(72,20000);//輔助串口3接收,超時(shí)時(shí)間為20ms
  USART_X_Init(USART2,36,9600); //可能的波特率(測(cè)試):  57600 、9600、115200
	
	USART_X_Init(USART3,36,9600);//接GPS模塊
  TIM3_Init(72,20000);//輔助串口3接收,超時(shí)時(shí)間為20ms
	
	//顯示初始化信息
  OLED_Clear_GRAM();
	OLED_DisplayString(0,0,16,"System Init..");
	OLED_Refresh_GRAM(); //刷新顯存
	
	//延時(shí)等待
	printf("延時(shí)等待rn");
	DelayMs(1000);
	DelayMs(1000);
	DelayMs(1000);
	DelayMs(1000);
	printf("開(kāi)始初始化SIM800C rn");
	
	//初始化SIM800C  
	OLED_DisplayString(0,16,16,"SIM800C Init..");
	OLED_Refresh_GRAM(); //刷新顯存
	while(1)
	{
			state=SIM800C_InitCheck();
			if(state==0)break;
			DelayMs(1000);
			printf("SIM800C初始化狀態(tài):%drn",state);
	}
	
	//設(shè)置文本模式
	OLED_DisplayString(0,32,16,"SIM800C Text Set...");
	OLED_Refresh_GRAM(); //刷新顯存
  while(1)
	{
			state=SIM800C_SetNoteTextMode();
			if(state==0)break;
			DelayMs(1000);
			printf("設(shè)置文本模式狀態(tài):%drn",state);
	}
	//同步網(wǎng)絡(luò)時(shí)間
	//SIM800C_NtpUpdate();
	
	//初始化GPRS
	SIM800C_GPRS_Init();
	while(1)
	{
     delay_ms(1);
     time_cnt++;
		 OneNet_Sendtime++;
     //記錄時(shí)間
     if(time_cnt>=100)
     {
         time_cnt=0;
				 DisplayState=!DisplayState;
         printf("切換頁(yè)面!rn");
     }
     
		 //向云端發(fā)送一次數(shù)據(jù)(每次選擇發(fā)送一種數(shù)據(jù))
		 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的數(shù)據(jù)
     DHT11_Read_Data(&dht11_temp,&dht11_humi);
     MQ_2=ADC1_GetCHx(8);
		 
		 //串口打印數(shù)據(jù)
//		 printf("溫度:%drn",dht11_temp);
//		 printf("濕度:%drn",dht11_humi);
//		 printf("MQ-2:%drn",MQ_2);
		 
		 //判斷煙霧是否超標(biāo),設(shè)置閥值
     if(MQ_2>=2000)
		 {
				//發(fā)送短信
				if(SIM800C_SendNote((u8*)"13800138000",sim800c_buff,strlen((char*)sim800c_buff))==0)
					printf("短信發(fā)送成功rn");
				else
					printf("短信發(fā)送失敗rn");
		 }
		 
		 
     //采用時(shí)間間隔切換頁(yè)面
     if(DisplayState)
     {
         DisplayPage2();
     }
     else 
     {
         DisplayPage1();
     }
     
		//實(shí)時(shí)接收WIFI收到的數(shù)據(jù)
     if(USART2_RX_FLAG)
     {
         USART2_RX_BUFF[USART2_RX_CNT]='?';
         USART2_RX_CNT=0;
         USART2_RX_FLAG=0;
			   printf("USART2_RX_BUFF=%srn",USART2_RX_BUFF);
         memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
     }
		 
		 //實(shí)時(shí)接收GPS收到的數(shù)據(jù)
     if(USART3_RX_FLAG)
     {
         USART3_RX_BUFF[USART3_RX_CNT]='?';
         USART3_RX_CNT=0;
         USART3_RX_FLAG=0;
				 //解析GPS經(jīng)緯度信息
				 GPS_GPRMC_Decoding(USART3_RX_BUFF,&Longitude,&latitude);
			   printf("經(jīng)度:%f,緯度:%frn",Longitude,latitude);
			   printf("USART2_RX_BUFF=%srn",USART3_RX_BUFF);
         memset(USART2_RX_BUFF,0,sizeof(USART3_RX_BUFF));
     }
	 }
}

/*
函數(shù)功能:  溫濕度DHT11顯示頁(yè)面
*/
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(); //刷新顯存
}


/*
函數(shù)功能:  煙霧傳感器顯示頁(yè)面
*/
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"

/*
函數(shù)功能:向SIM800C模塊發(fā)送指令
函數(shù)參數(shù):
				char *cmd  發(fā)送的命令
			  char *check_data 檢測(cè)返回的數(shù)據(jù)
返回值: 0表示成功 1表示失敗
*/
u8 SIM800C_SendCmd(char *cmd,char *check_data)
{
   u16 i,j;
   for(i=0;i<5;i++) //測(cè)試的總次數(shù)
   {
      USART2_RX_FLAG=0;
      USART2_RX_CNT=0;
			memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
			USART_X_SendString(USART2,cmd); //發(fā)送指令
      for(j=0;j<500;j++) //等待的時(shí)間(ms單位)
      {
          if(USART2_RX_FLAG)
          {
              USART2_RX_BUFF[USART2_RX_CNT]='?';
              if(strstr((char*)USART2_RX_BUFF,check_data))
              {
                  return 0;
              }
              else break;
          }
          delay_ms(20); //一次的時(shí)間
      }
   }
   return 1;
}


/*
函數(shù)  功能:GSM模塊初始化檢測(cè)
函數(shù)返回值:1表示模塊檢測(cè)失敗,0表示成功
*/
u8 SIM800C_InitCheck(void)
{
	  if(SIM800C_SendCmd("ATrn","OK"))return 1;
	  else printf("SIM800模塊正常!rn");
	  
		if(SIM800C_SendCmd("ATE0rn","OK"))return 2;
	  else printf("設(shè)置模塊不回顯成功!rn");
	
		if(SIM800C_SendCmd("AT+CGMIrn","OK"))return 3;
		else printf("查詢(xún)制造商名稱(chēng)成功!%srn",USART2_RX_BUFF);
	
		if(SIM800C_SendCmd("AT+CGMMrn","OK"))return 4;
		else printf("查詢(xún)模塊型號(hào)成功!%srn",USART2_RX_BUFF);
		
	  DelayMs(1000);
		DelayMs(1000);
		if(SIM800C_SendCmd("AT+CNUMrn","+CNUM:"))return 5;
		else printf("獲取本機(jī)號(hào)碼成功!%srn",USART2_RX_BUFF);
	  /* 返回格式如下:
		+CNUM: "","+8613086989413",145,7,4
		OK
		*/
		return 0;
}

/*
函數(shù)  功能:GSM模塊短信模式設(shè)置
函數(shù)返回值:0表示模塊設(shè)置成功
*/
u8 SIM800C_SetNoteTextMode(void)
{
		if(SIM800C_SendCmd("AT+CSCS="GSM"rn","OK"))return 1;// "GSM"字符集
		else printf("短信GSM字符集設(shè)置成功!rn");
	
	  if(SIM800C_SendCmd("AT+CMGF=1rn","OK"))return 2; //文本模式
		else printf("短信文本模式設(shè)置成功!rn");
		return 0;
}

/*
函數(shù)功能:發(fā)送短信
函數(shù)參數(shù):
					num:電話號(hào)碼
					text:短信內(nèi)容
函數(shù)返回值:0表示發(fā)送成功
*/
u8 SIM800C_SendNote(u8 *num,u8 *text,u16 len)
{
		char data[50];
		char send_buf[2];
		sprintf(data,"AT+CMGS="%s"rn",num);
		if(SIM800C_SendCmd(data,">"))return 1; //設(shè)置發(fā)送的手機(jī)號(hào)
		USART_X_SendData(USART2,text,len);     //發(fā)送短信內(nèi)容
	
		send_buf[0] = 0x1a;
		send_buf[1] = '?';
	  if(SIM800C_SendCmd(send_buf,"+CMGS"))return 2; //發(fā)送結(jié)束符號(hào)
		return 0;
}


/*
函數(shù)功能:NTP網(wǎng)絡(luò)同步時(shí)間
*/
void SIM800C_NtpUpdate(void)
{  
	 SIM800C_SendCmd("AT+SAPBR=3,1,"Contype","GPRS"rn","OK");//配置承載場(chǎng)景1
	 SIM800C_SendCmd("AT+SAPBR=3,1,"APN","CMNET"rn","OK");
	 SIM800C_SendCmd("AT+SAPBR=1,1rn","OK");                     //激活一個(gè)GPRS上下文
   DelayMs(5);
   SIM800C_SendCmd("AT+CNTPCID=1rn","OK");                     //設(shè)置CNTP使用的CID
	 SIM800C_SendCmd("AT+CNTP="202.120.2.101",32rn","OK");     //設(shè)置NTP服務(wù)器和本地時(shí)區(qū)(32時(shí)區(qū) 時(shí)間最準(zhǔn)確)
   SIM800C_SendCmd("AT+CNTPrn","+CNTP: 1");                    //同步網(wǎng)絡(luò)時(shí)間
	 printf("同步網(wǎng)絡(luò)時(shí)間:%srn",USART2_RX_BUFF);
}


/*
函數(shù)功能:GPRS數(shù)據(jù)通信初始化
返 回 值: 0表示成功
*/
u8 SIM800C_GPRS_Init(void)
{
	 SIM800C_SendCmd("AT+CIPCLOSE=1rn","CLOSE OK");	//關(guān)閉連接
	 SIM800C_SendCmd("AT+CIPSHUTrn","SHUT OK");		//關(guān)閉移動(dòng)場(chǎng)景 
	 if(SIM800C_SendCmd("AT+CGCLASS="B"rn","OK"))return 1;				//設(shè)置GPRS移動(dòng)臺(tái)類(lèi)別為B,支持包交換和數(shù)據(jù)交換 
	 if(SIM800C_SendCmd("AT+CGDCONT=1,"IP","CMNET"rn","OK"))return 2;//設(shè)置PDP上下文,互聯(lián)網(wǎng)接協(xié)議,接入點(diǎn)等信息
	 if(SIM800C_SendCmd("AT+CGATT=1rn","OK"))return 3;					//附著GPRS業(yè)務(wù)
	 if(SIM800C_SendCmd("AT+CIPCSGP=1,"CMNET"rn","OK"))return 4;	 	//設(shè)置為GPRS連接模式
	 if(SIM800C_SendCmd("AT+CIPHEAD=1rn","OK"))return 5;	 				//設(shè)置接收數(shù)據(jù)顯示IP頭(方便判斷數(shù)據(jù)來(lái)源)
	 return 0;
}

/*
函數(shù)功能: 連接TCP服務(wù)器
函數(shù)參數(shù): 
				ipaddr:ip地址
				port:端口 
返 回 值: 0表示成功,其他值表示失敗
*/
u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port)
{
	 char cmd_buff[100];
	 SIM800C_SendCmd("AT+CIPCLOSE=1rn","CLOSE OK");	//關(guān)閉連接
	 SIM800C_SendCmd("AT+CIPSHUTrn","SHUT OK");		//關(guān)閉移動(dòng)場(chǎng)景 
	 sprintf(cmd_buff,"AT+CIPSTART="TCP","%s","%s"rn",ipaddr,port);
	 if(SIM800C_SendCmd(cmd_buff,"OK"))return 1;		//發(fā)起連接
	 return 0;
}


/*
函數(shù)功能: TCP客戶(hù)端模式下發(fā)送數(shù)據(jù)
返 回 值: 0表示成功,其他值表示失敗
*/
u8 SIIM800C_TCP_SendData(u8 *data,u32 len)
{
	 char send_buf[2];
	//準(zhǔn)備發(fā)送數(shù)據(jù)
	 if(SIM800C_SendCmd("AT+CIPSENDrn",">")==0)
	 {
		  //發(fā)送數(shù)據(jù)
			USART_X_SendData(USART2,data,len);
		  //發(fā)送結(jié)束符號(hào)
		  DelayMs(50);
		  send_buf[0] = 0x1a;
		  send_buf[1] = '?';
		  if(SIM800C_SendCmd(send_buf,"SEND OK"))return 2;
		  else 	return 0;
	 }
	 return 1;
}

/*
函數(shù)功能: 采用HTTP協(xié)議方式向OneNet服務(wù)器上報(bào)數(shù)據(jù)
函數(shù)參數(shù):
				char *data_point:數(shù)據(jù)點(diǎn)的名稱(chēng)
				u32 data :上傳的數(shù)據(jù)
*/
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)
{
		//拼接數(shù)據(jù)
	  snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),
			"{"datastreams":[{"id":"%s","datapoints":[{"value":%d}]}]}",data_point,data);

		//拼接數(shù)據(jù)
		snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),
			"POST /devices/%s/datapoints HTTP/1.1rn" 
			"api-key:%srn" 
			"Host:api.heclouds.comrn" 
			"Connection:closern" 
			"Content-Length:%drn" 
			"rn" 
			"%s",
	    ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF
		);
		printf("OneNet_HTTP_CMD=%srn",OneNet_HTTP_CMD);
		
		printf("連接服務(wù)器的狀態(tài):%drn",SIM800C_Connect_TCP_Server("183.230.40.33","80"));
		DelayMs(500);
		printf("數(shù)據(jù)發(fā)送的狀態(tài):%drn",SIIM800C_TCP_SendData((u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD)));
}

/*
函數(shù)功能: 采用HTTP協(xié)議方式向OneNet服務(wù)器上報(bào)GPS經(jīng)緯度信息
函數(shù)參數(shù):
				char *data_point:數(shù)據(jù)點(diǎn)的名稱(chēng)
				double Longitude,double latitude:上傳的經(jīng)緯度數(shù)據(jù)
*/
void OneNet_HTTP_GPS_DataUpdate(char *data_point,double Longitude,double latitude)
{
		//拼接數(shù)據(jù)
	  snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),
			"{"datastreams":[{"id":"%s","datapoints":[{"value":{"lon":%lf,"lat":%lf}}]}]}",
		   data_point,Longitude,latitude);

		//拼接數(shù)據(jù)
		snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),
			"POST /devices/%s/datapoints HTTP/1.1rn" 
			"api-key:%srn" 
			"Host:api.heclouds.comrn" 
			"Connection:closern" 
			"Content-Length:%drn" 
			"rn" 
			"%s",
	    ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF
		);
		printf("GPS_OneNet_HTTP_CMD=%srn",OneNet_HTTP_CMD);
		
		printf("連接服務(wù)器的狀態(tài):%drn",SIM800C_Connect_TCP_Server("183.230.40.33","80"));
		DelayMs(500);
		printf("數(shù)據(jù)發(fā)送的狀態(tài):%drn",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

四、創(chuàng)建應(yīng)用

發(fā)布的鏈接:??https://open.iot.10086.cn/iotbox/appsquare/appview?openid=6b5f9941b4d0464671fa1bb6cd3511dc

  • 更多詳細(xì)資料請(qǐng)聯(lián)系.docx
    下載

相關(guān)推薦