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

发布者:RadiantBreeze最新更新时间:2022-10-14 来源: csdn关键字:STM32  SIM800C  MQTT协议  OneNet  GPS数据 手机看文章 扫描二维码
随时随地手机看文章

一、环境介绍

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

#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("串口初始化完成!rn");

OLED_Init();         //OLED显示屏初始化

  ADC1_Init();

if(DHT11_Init())printf("DHT11检测错误!rn");

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("延时等待rn");

DelayMs(1000);

DelayMs(1000);

DelayMs(1000);

DelayMs(1000);

printf("开始初始化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初始化状态:%drn",state);

}

//设置文本模式

OLED_DisplayString(0,32,16,"SIM800C Text Set...");

OLED_Refresh_GRAM(); //刷新显存

  while(1)

{

state=SIM800C_SetNoteTextMode();

if(state==0)break;

DelayMs(1000);

printf("设置文本模式状态:%drn",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("切换页面!rn");

     }

     

//向云端发送一次数据(每次选择发送一种数据)

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("温度:%drn",dht11_temp);

// printf("湿度:%drn",dht11_humi);

// printf("MQ-2:%drn",MQ_2);

 

//判断烟雾是否超标,设置阀值

     if(MQ_2>=2000)

{

//发送短信

if(SIM800C_SendNote((u8*)"13800138000",sim800c_buff,strlen((char*)sim800c_buff))==0)

printf("短信发送成功rn");

else

printf("短信发送失败rn");

}

 

 

     //采用时间间隔切换页面

     if(DisplayState)

     {

         DisplayPage2();

     }

     else 

     {

         DisplayPage1();

     }

     

//实时接收WIFI收到的数据

     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));

     }

 

//实时接收GPS收到的数据

     if(USART3_RX_FLAG)

     {

         USART3_RX_BUFF[USART3_RX_CNT]='';

         USART3_RX_CNT=0;

         USART3_RX_FLAG=0;

//解析GPS经纬度信息

GPS_GPRMC_Decoding(USART3_RX_BUFF,&Longitude,&latitude);

   printf("经度:%f,纬度:%frn",Longitude,latitude);

   printf("USART2_RX_BUFF=%srn",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]='';

              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("ATrn","OK"))return 1;

  else printf("SIM800模块正常!rn");

  

if(SIM800C_SendCmd("ATE0rn","OK"))return 2;

  else printf("设置模块不回显成功!rn");

if(SIM800C_SendCmd("AT+CGMIrn","OK"))return 3;

else printf("查询制造商名称成功!%srn",USART2_RX_BUFF);

if(SIM800C_SendCmd("AT+CGMMrn","OK"))return 4;

else printf("查询模块型号成功!%srn",USART2_RX_BUFF);

  DelayMs(1000);

DelayMs(1000);

if(SIM800C_SendCmd("AT+CNUMrn","+CNUM:"))return 5;

else printf("获取本机号码成功!%srn",USART2_RX_BUFF);

  /* 返回格式如下:

+CNUM: "","+8613086989413",145,7,4

OK

*/

return 0;

}

 

/*

函数  功能:GSM模块短信模式设置

函数返回值:0表示模块设置成功

*/

u8 SIM800C_SetNoteTextMode(void)

{

if(SIM800C_SendCmd("AT+CSCS="GSM"rn","OK"))return 1;// "GSM"字符集

else printf("短信GSM字符集设置成功!rn");

  if(SIM800C_SendCmd("AT+CMGF=1rn","OK"))return 2; //文本模式

else printf("短信文本模式设置成功!rn");

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"rn",num);

if(SIM800C_SendCmd(data,">"))return 1; //设置发送的手机号

USART_X_SendData(USART2,text,len);     //发送短信内容

send_buf[0] = 0x1a;

send_buf[1] = '';

  if(SIM800C_SendCmd(send_buf,"+CMGS"))return 2; //发送结束符号

return 0;

}

 

 

/*

函数功能:NTP网络同步时间

*/

void SIM800C_NtpUpdate(void)

{  

SIM800C_SendCmd("AT+SAPBR=3,1,"Contype","GPRS"rn","OK");//配置承载场景1

SIM800C_SendCmd("AT+SAPBR=3,1,"APN","CMNET"rn","OK");

SIM800C_SendCmd("AT+SAPBR=1,1rn","OK");                     //激活一个GPRS上下文

   DelayMs(5);

   SIM800C_SendCmd("AT+CNTPCID=1rn","OK");                     //设置CNTP使用的CID

[1] [2]
关键字:STM32  SIM800C  MQTT协议  OneNet  GPS数据 引用地址:STM32+SIM800C采用MQTT协议登录OneNet上传温湿度、MQ2烟雾浓度、GPS数据

上一篇:STM32+移远MC20模块采用MQTT协议登录OneNet上传GPS数据
下一篇:STM32+果云GA6-GPRS/GSM模块+MQTT+HTTP协议连接中移OneNet上传GPS数据定位

推荐阅读最新更新时间:2024-11-12 10:47

STM32 双DAC DMA TIM6输出正弦波例子
STM32F103有双DAC通道,利用DMA实现2个波形输出 #include stm32f10x.h //DAC1,2初始化 void dac_init(void) { RCC- APB2ENR |= RCC_APB2ENR_IOPAEN; //开启端口A时钟 RCC- APB1ENR |= RCC_APB1ENR_DACEN; //开启DAC时钟 GPIOA- CRL &= 0xff00ffff; //PA4,PA5模拟输入 DAC- CR = DAC_CR_TEN1 | DAC_CR_TEN2; //开启触发使能才能设置触发模式 //开启DAC,关闭输出缓存,TI
[单片机]
STM32之中断嵌套控制器
STM32 (Cortex-M3) 中的优先级概念 STM32(Cortex-M3)中有两个优先级的概念:抢占式优先级和响应优先级,也把响应优先级称作“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。 1. 何为占先式优先级(pre-emption priority) 高占先式优先级的中断事件会打断当前的主程序/中断程序运行—抢断式优先响应,俗称中断嵌套。 2. 何为副优先级(subpriority) 在占先式优先级相同的情况下,高副优先级的中断优先被响应; 在占先式优先级相同的情况下,如果有低副优先级中断正在执行, 高副优先级的中断要等待已被响应的低副优先级中断执行结束后才能得到响应—非抢断
[单片机]
ADIS16203角度传感器的stm32驱动实现要点
一、前言 ADIS16203是一款完整的倾斜角测量系统,采用ADI公司的 iSensor™集成技术制造,全部功能均集成于一个紧凑的封装中。该器件采用嵌入式信号处理解决方案来增强ADI公司的 iMEMS®传感器技术,可提供适当格式的工厂校准、传感器数字倾斜角数据,从而利用串行外设接口(SPI)即可方便地访问数据。通过SPI接口可以访问多个测量结果:360°线性倾斜角、±180°线性倾斜角、温度、电源和一个辅助模拟输入。由于可以轻松访问校准的数字传感器数据,因此开发者能够获得可立即供系统使用的器件,使开发时间、成本和编程风险得以减少。 通过数个内置特性,如单命令失调校准等,以及方便的采样速率控制和带宽控制,该器件很容易适应终端系统
[单片机]
ADIS16203角度传感器的<font color='red'>stm32</font>驱动实现要点
关于STM32的I2C硬件DMA实现
网上看到很多说STM32的I2C很难用,但我觉得还是理解上的问题,STM32的I2C确实很复杂,但只要基础牢靠,并没有想象中的那么困难。 那么就先从基础说起,只说关键点,不涉及代码。 首先说I2C这个协议:协议包括START、ACK、NACK、STOP。尽管协议中规定START必须,其他几个非必须,但实际上其他三个仍旧非常重要。 主发从收:主 START - 主发地址 - 从 ACK - (主发数据 - 从 ACK (循环)) - 主 STOP 或 主 START 启动下一次传输 这一过程中,主控SCL线,从只在ACK时控SDA线,其他时刻主控SDA线。 主收从发:主 START - 从发地址 - 主 ACK - (从发数据 -
[单片机]
STM32开发笔记69: 外设启动的先后次序
单片机型号:STM32F070F6P6 今天,在程序框架中增加了Timer16定时器驱动,但程序不能正常运行,本篇日志记录其原因。 驱动程序框架,定义了回调函数Timer16_InterruptFunction,写在main.cpp中用于逻辑层设计。Timer16_InterruptFunction调用的间隔为1ms,具体程序如下: void Timer16_InterruptFunction(void) { Target.HAL.L2.Turn(); } 此程序完成以1ms为间隔L2闪烁的程序,但是将此程序烧写到目标板后,程序不能正常运行。经过调试,最后将问题锁定在启动顺序上,看一下程序外设的启动顺序,具体程序
[单片机]
STM32读写TXT文件(可追加数据)的示例代码
/* 说明: * 下面的函数是测试在已有的 大海.txt 文件下继续添加数据 * 测试条件在TF卡中建立 大海.txt 文件,并在文件中添加内容,测试过程中可以分别添加 512数据,=512数据, 512数据进行分别测试 * 作者:Flame * 测试时间:20130711 */ unsigned int FATFSNumSize;//文件大小存储变量,为了查看方便放到函数外部 void OutPutFile(void) { unsigned int a; FILINFO finfo; DIR dirs; char path ={ }; //目录名为空,表示是根目
[单片机]
STM32串口的485收发控制角的电平控制
关于485电平控制,如果在发送中断处理后边直接电平转换,会导致发送数据不全,如果加入一定延时,然后在进行电平转换,可以解决这个问题,但略显笨重。解决方法是开启发送完成中断:USART_IT_TC(Transmission complete interrupt)可以完成精准控制,需要注意的是,这个中断没发送完一个字节都会产生,因此建议在最后一个字节装入发送缓存器后再开启。 void USART1_IRQHandler(void) { CPU_INT08U rx_data; CPU_INT08U tx_data; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
[单片机]
stm32的中断与事件
事件:是表示检测有一某件触发事件发生了。 中断:有某个事件发生并产生中断,并跳转到对应的中断处理程序中。 事件可以触发中断,也可以不触发 中断有可能被更优先的中断屏蔽,事件不会 事件本质上就是一个触发信号,是用来触发特定的外设模块或核心本身(唤醒). 事件只是一个触发信号(脉冲),而中断则是一个固定的电平信号
[单片机]
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved