基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3))

系统实现的功能

系统实现的是运用一块STM32F103C8T6作为发射端节点,上面搭载NRF2401(2.4G)并连上温湿度模块,外加一块STM32F103C8T6作为接收端节点,上面搭上气体传感器,0.96寸OLED显示屏,NRF2401(2.4G)作为接收端,通过ESP8266WiFi模块上传阿里云,并在阿里云上面的IOT Studio 显示自己的数据,当然我也自己写了自己的js界面,显示在自己本地上面的浏览器上。整体功能显示基本完成,NRF2401(2.4模块)上已经实现,过程还是挺充实




也可以在自己上面阿里云上面通过物理模型实现数据的可视化web界面设置。
简易的实现自己的一系列功能时,可能你以为就实现了?其实还有自己实现的可以自己web端实现的功能,自己运用的node.js架构后台,然后运用阿里云上面的AMQP服务端订阅功能实现对数据的下发和显示

实现的代码如下

一.发射端上面发送数据

温湿度DHT117+无线通信模块作为远节点的温湿度结点(发射端)主函数代码实现:
通过传感器采集模块,在监测的周遭环境上由模值转化为数据,通过OUT管脚输出数据,同时交一个无线传输模块作为一个远节点,
(1)main.c

#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include "DTH117.h"
#include "sys.h"
#include "SPI_NRF.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>u8 status;  //用于判断接收/发送状态
u8 txbuf[2];     //发送缓冲
u8 rxbuf[4];//接收缓冲
int i=0;
/*
*读取温湿度传感器DHT11的值,并用串口打印出来
*/
void clock_init(void);
u8 temp = 0,humi = 0;int main(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SPI_NRF_Init();delay_init();DHT11_Init();   clock_init();  usart_init(115200);     //初始化串口printf("\r\n 这是一个 NRF24L01 无线传输实验 \r\n");printf("\r\n 这是无线传输 主机端 的反馈信息\r\n");printf("\r\n   正在检测NRF与MCU是否正常连接。。。\r\n");/*检测NRF模块与MCU的连接*/status = NRF_Check(); /*判断连接状态*/  if(status == SUCCESS)       printf("\r\n      NRF与MCU连接成功!\r\n");  else   printf("\r\n  NRF与MCU连接失败,请重新检查接线。\r\n"); while(1){  DHT11_Read_Data(&temp,&humi);printf("\r\n 主机端 进入自应答发送模式\r\n"); NRF_TX_Mode();txbuf[0]=temp;          txbuf[1]=humi;status = NRF_Tx_Dat(txbuf);//这里只设置为发给进入接收模式的无线模块 /*以下注释的代码是对无线通信模块相互收发一体模式,我在这里没有对接收端下发指令给接收端,所以这部分我注释了,就是没有实现将这里模块实现最大程度上面的收发一体,仅仅是将一个作为发射端,一个作为接收端 */ //         switch(status)
//          {//            case MAX_RT:
//                  printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
//               break;
//
//            case ERROR:
//                  printf("\r\n 未知原因导致发送失败。 \r\n");
//               break;
//
//            case TX_DS:
//                  printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");
//               break;
//          }
//      printf("\r\n 主机端 进入接收模式。 \r\n");
//      NRF_RX_Mode();
//      status = NRF_Rx_Dat(rxbuf);
//          switch(status){//           case RX_DR:
//              for(i=0;i<300;i++)
//              {
//                  printf("\r\n 主机端 接收到 从机端 发送的数据为:%d \r\n",rxbuf[i]);
//                  txbuf[i] =rxbuf[i];
//
//              }
//                break;case ERROR:printf("\r\n 主机端 接收出错。   \r\n");break;         }}}
// }/**************************************************************************
函数名:void clock_init(void)
参数说明:无
返回值:无
函数作用:开启高速外部时钟,
ADCCLK设置为12MHZ,  SYSCLK设置为72Mhz,PCLK1设置为36MHZ,PKLC2设置为72mhz
***************************************************************************/void clock_init(void){RCC->CR = 0x1010000;RCC->CFGR = 0x1DC402;
}

(2).无线通信模块(管脚定义)SPI_NRF.c

/************************************************************* 文件名  :SPI_NRF.c* 描述    :SPI_NRF24L01+无线模块应用函数库         * 实验平台: STM32开发板* 硬件连接:-----------------------------|*          |                           |*          |     PA1            : NRF- CSN ||    PA5-SPI1-SCK   : NRF -SCK ||    PA6-SPI1-MISO  : NRF -MISO||    PA7-SPI1-MOSI  : NRF -MOSI||    PA3            : NRF-IRQ  ||    PA2            : NRF-CE   |*          |                           |*           -----------------------------* 管脚没有特别的要求需要这样的定义
**********************************************************************************/
#include "SPI_NRF.h"
#include "usart.h"
#include "delay.h"u8 RX_BUF[RX_PLOAD_WIDTH];      //接收数据缓存u8 TX_BUF[TX_PLOAD_WIDTH];      //发射数据缓存u8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址u8 RX_ADDRESS[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};/** 函数名:SPI_NRF_Init* 描述  :SPI的 I/O配置用*/
void SPI_NRF_Init(void)
{SPI_InitTypeDef  SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;/*使能GPIOB,GPIOD,复用功能时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);/*使能SPI1时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);/*配置 SPI_NRF_SPI的 SCK,MISO,MOSI引脚,GPIOA^5,GPIOA^6,GPIOA^7 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能GPIO_Init(GPIOA, &GPIO_InitStructure);  /*配置SPI_NRF_SPI的CE引脚,GPIOA^2和SPI_NRF_SPI的 CSN 引脚: NSS GPIOA^1*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);/*配置SPI_NRF_SPI的IRQ引脚,GPIOA^3*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;  //上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure); /* 这是自定义的宏,用于拉高csn引脚,NRF进入空闲状态 */NRF_CSN_HIGH(); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      //主模式SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                 //数据大小8位SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                     //时钟极性,空闲时为低SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                        //第1个边沿有效,上升沿为采样时刻SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                         //NSS信号由软件产生SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;  //8分频,9MHzSPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;               //高位在前SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);/* Enable SPI1  */SPI_Cmd(SPI1, ENABLE);
}

二.接收端接收数据+上传阿里云

接收端接收的数据就是来自发射端上面的数据,通时自己在接收端上还实现了对MQ-3气体传感器的处理,同时自己在考虑这个数据的直观性还是用了一个OLED显示屏实现数据的客观处理。
(1)气体传感器ADC.c

 #include "adc.h"#include "delay.h"#include "stm32f10x_adc.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//All rights reserved
//
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void Adc_Init(void)
{   ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );    //使能ADC1通道时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M//PA1 作为模拟通道输入引脚                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        //模拟输入引脚GPIO_Init(GPIOA, &GPIO_InitStructure);  ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    //ADC工作模式:ADC1和ADC2工作在独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE;    //模数转换工作在单通道模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  //模数转换工作在单次转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1;  //顺序进行规则转换的ADC通道的数目ADC_Init(ADC1, &ADC_InitStructure);  //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   ADC_Cmd(ADC1, ENABLE);  //使能指定的ADC1ADC_ResetCalibration(ADC1);  //使能复位校准  while(ADC_GetResetCalibrationStatus(ADC1));   //等待复位校准结束ADC_StartCalibration(ADC1);    //开启AD校准while(ADC_GetCalibrationStatus(ADC1));  //等待校准结束ADC_SoftwareStartConvCmd(ADC1, ENABLE);        //使能指定的ADC1的软件转换启动功能}
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{//设置指定ADC的规则组通道,一个序列,采样时间ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );  //ADC1,ADC通道,采样时间为239.5周期                   ADC_SoftwareStartConvCmd(ADC1, ENABLE);     //使能指定的ADC1的软件转换启动功能    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}u16 Get_Adc_Average(u8 ch,u8 times)
{u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);Delay_Ms(5);}return temp_val/times;
}    

(2).main.c

/*-----------------------------------------------------*/
/*              超纬电子STM32系列开发板                */
/*-----------------------------------------------------*/
/*                     程序结构                        */
/*-----------------------------------------------------*/
/*USER     :包含程序的main函数,是整个程序的入口      */
/*HARDWARE :包含开发板各种功能外设的驱动程序          */
/*CORE     :包含STM32的核心程序,官方提供,我们不修改 */
/*STLIB    :官方提供的库文件,我们不修改              */
/*-----------------------------------------------------*/
/*                                                     */
/*           程序main函数,入口函数源文件              */
/*                                                     */
/*-----------------------------------------------------*/#include "stm32f10x.h"  //包含需要的头文件
#include "main.h"       //包含需要的头文件
#include "delay.h"      //包含需要的头文件
#include "usart1.h"     //包含需要的头文件
#include "usart2.h"     //包含需要的头文件
#include "timer1.h"     //包含需要的头文件
#include "timer2.h"     //包含需要的头文件
#include "timer3.h"     //包含需要的头文件
#include "timer4.h"     //包含需要的头文件
#include "wifi.h"     //包含需要的头文件
#include "led.h"        //包含需要的头文件
#include "mqtt.h"       //包含需要的头文件
#include "key.h"        //包含需要的头文件
#include "dht11.h"      //包含需要的头文件
#include "oled.h"
#include "sys.h"
#include "adc.h"
#include "SPI_NRF.h"int main(void)
{   Delay_Init();                   //延时功能初始化              Usart1_Init(9600);              //串口1功能初始化,波特率9600Usart2_Init(115200);            //串口2功能初始化,波特率115200 TIM4_Init(300,7200);            //TIM4初始化,定时时间 300*7200*1000/72000000 = 30msLED_Init();                     //LED初始化OLED_Init();Adc_Init();SPI_NRF_Init();WiFi_ResetIO_Init();            //初始化WiFi的复位IOMQTT_Buff_Init();               //初始化接收,发送,命令数据的 缓冲区 以及各状态参数AliIoT_Parameter_Init();        //初始化连接阿里云IoT平台MQTT服务器的参数   OLED_Clear();OLED_Display_On();OLED_ShowCHinese(40,0,0);OLED_ShowCHinese(60,0,1);OLED_ShowCHinese(80,0,2);OLED_ShowCHinese(100,0,3);//显示各个参数的中文OLED_ShowCHinese(0,2,4);OLED_ShowCHinese(18,2,5);     OLED_ShowString(35,2, ":",16);//显示温度中文OLED_ShowCHinese(0,4,6);OLED_ShowCHinese(18,4,7);   OLED_ShowString(35,4, ":",16);//显示温度中文   while(1)                        //主循环{      /*--------------------------------------------------------------------*//*   Connect_flag=1同服务器建立了连接,我们可以发布数据和接收推送了    *//*--------------------------------------------------------------------*/if(Connect_flag==1){     /*-------------------------------------------------------------*//*                     处理发送缓冲区数据                      *//*-------------------------------------------------------------*/if(MQTT_TxDataOutPtr != MQTT_TxDataInPtr){                //if成立的话,说明发送缓冲区有数据了//3种情况可进入if//第1种:0x10 连接报文//第2种:0x82 订阅报文,且ConnectPack_flag置位,表示连接报文成功//第3种:SubcribePack_flag置位,说明连接和订阅均成功,其他报文可发if((MQTT_TxDataOutPtr[2]==0x10)||((MQTT_TxDataOutPtr[2]==0x82)&&(ConnectPack_flag==1))||(SubcribePack_flag==1)){    u1_printf("发送数据:0x%x\r\n",MQTT_TxDataOutPtr[2]);  //串口提示信息MQTT_TxData(MQTT_TxDataOutPtr);                       //发送数据MQTT_TxDataOutPtr += BUFF_UNIT;                       //指针下移if(MQTT_TxDataOutPtr==MQTT_TxDataEndPtr)              //如果指针到缓冲区尾部了MQTT_TxDataOutPtr = MQTT_TxDataBuf[0];            //指针归位到缓冲区开头}              }//处理发送缓冲区数据的else if分支结尾/*-------------------------------------------------------------*//*                     处理接收缓冲区数据                      *//*-------------------------------------------------------------*/if(MQTT_RxDataOutPtr != MQTT_RxDataInPtr){  //if成立的话,说明接收缓冲区有数据了                                                      u1_printf("接收到数据:");/*-----------------------------------------------------*//*                    处理CONNACK报文                  *//*-----------------------------------------------------*/               //if判断,如果第一个字节是0x20,表示收到的是CONNACK报文//接着我们要判断第4个字节,看看CONNECT报文是否成功if(MQTT_RxDataOutPtr[2]==0x20){                         switch(MQTT_RxDataOutPtr[5]){                   case 0x00 : u1_printf("CONNECT报文成功\r\n");                            //串口输出信息 ConnectPack_flag = 1;                                        //CONNECT报文成功,订阅报文可发break;                                                       //跳出分支case 0x00                                              case 0x01 : u1_printf("连接已拒绝,不支持的协议版本,准备重启\r\n");     //串口输出信息Connect_flag = 0;                                            //Connect_flag置零,重启连接break;                                                       //跳出分支case 0x01   case 0x02 : u1_printf("连接已拒绝,不合格的客户端标识符,准备重启\r\n"); //串口输出信息Connect_flag = 0;                                            //Connect_flag置零,重启连接break;                                                       //跳出分支case 0x02 case 0x03 : u1_printf("连接已拒绝,服务端不可用,准备重启\r\n");         //串口输出信息Connect_flag = 0;                                            //Connect_flag置零,重启连接break;                                                       //跳出分支case 0x03case 0x04 : u1_printf("连接已拒绝,无效的用户名或密码,准备重启\r\n");   //串口输出信息Connect_flag = 0;                                            //Connect_flag置零,重启连接                      break;                                                       //跳出分支case 0x04case 0x05 : u1_printf("连接已拒绝,未授权,准备重启\r\n");               //串口输出信息Connect_flag = 0;                                            //Connect_flag置零,重启连接                       break;                                                       //跳出分支case 0x05        default   : u1_printf("连接已拒绝,未知状态,准备重启\r\n");             //串口输出信息 Connect_flag = 0;                                            //Connect_flag置零,重启连接                   break;                                                       //跳出分支case default                                 }               }           //if判断,第一个字节是0x90,表示收到的是SUBACK报文//接着我们要判断订阅回复,看看是不是成功else if(MQTT_RxDataOutPtr[2]==0x90){ switch(MQTT_RxDataOutPtr[6]){                  case 0x00 :case 0x01 : u1_printf("订阅成功\r\n");            //串口输出信息SubcribePack_flag = 1;                //SubcribePack_flag置1,表示订阅报文成功,其他报文可发送Ping_flag = 0;                        //Ping_flag清零TIM3_ENABLE_30S();                    //启动30s的PING定时器TIM2_ENABLE_30S();                    //启动30s的上传数据的定时器TempHumi_State();                     //先发一次数据break;                                //跳出分支                                             default   : u1_printf("订阅失败,准备重启\r\n");  //串口输出信息 Connect_flag = 0;                     //Connect_flag置零,重启连接break;                                //跳出分支                              }                   }//if判断,第一个字节是0xD0,表示收到的是PINGRESP报文else if(MQTT_RxDataOutPtr[2]==0xD0){ u1_printf("PING报文回复\r\n");          //串口输出信息 if(Ping_flag==1){                     //如果Ping_flag=1,表示第一次发送Ping_flag = 0;                     //要清除Ping_flag标志}else if(Ping_flag>1){                   //如果Ping_flag>1,表示是多次发送了,而且是2s间隔的快速发送Ping_flag = 0;                       //要清除Ping_flag标志TIM3_ENABLE_30S();                  //PING定时器重回30s的时间}                }   //if判断,如果第一个字节是0x30,表示收到的是服务器发来的推送数据//我们要提取控制命令else if((MQTT_RxDataOutPtr[2]==0x30)){ u1_printf("服务器等级0推送\r\n");         //串口输出信息 MQTT_DealPushdata_Qs0(MQTT_RxDataOutPtr);  //处理等级0推送数据}             MQTT_RxDataOutPtr += BUFF_UNIT;                     //指针下移if(MQTT_RxDataOutPtr==MQTT_RxDataEndPtr)            //如果指针到缓冲区尾部了MQTT_RxDataOutPtr = MQTT_RxDataBuf[0];          //指针归位到缓冲区开头                        }//处理接收缓冲区数据的else if分支结尾/*-------------------------------------------------------------*//*                     处理命令缓冲区数据                      *//*-------------------------------------------------------------*/if(MQTT_CMDOutPtr != MQTT_CMDInPtr){                             //if成立的话,说明命令缓冲区有数据了                u1_printf("命令:%s\r\n",&MQTT_CMDOutPtr[2]);                 //串口输出信息MQTT_CMDOutPtr += BUFF_UNIT;                               //指针下移if(MQTT_CMDOutPtr==MQTT_CMDEndPtr)                          //如果指针到缓冲区尾部了MQTT_CMDOutPtr = MQTT_CMDBuf[0];                          //指针归位到缓冲区开头               }//处理命令缓冲区数据的else if分支结尾    }//Connect_flag=1的if分支的结尾/*--------------------------------------------------------------------*//*      Connect_flag=0同服务器断开了连接,我们要重启连接服务器         *//*--------------------------------------------------------------------*/else{ u1_printf("需要连接服务器\r\n");                 //串口输出信息TIM_Cmd(TIM4,DISABLE);                           //关闭TIM4 TIM_Cmd(TIM3,DISABLE);                           //关闭TIM3  WiFi_RxCounter=0;                                //WiFi接收数据量变量清零                        memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE);          //清空WiFi接收缓冲区 if(WiFi_Connect_IoTServer()==0){                    //如果WiFi连接云服务器函数返回0,表示正确,进入ifu1_printf("建立TCP连接成功\r\n");            //串口输出信息Connect_flag = 1;                            //Connect_flag置1,表示连接成功   WiFi_RxCounter=0;                            //WiFi接收数据量变量清零                        memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE);      //清空WiFi接收缓冲区 MQTT_Buff_ReInit();                          //重新初始化发送缓冲区                    }              }}
}
/*-------------------------------------------------*/
/*函数名:采集温湿度,并发布给服务器               */
/*参  数:无                                       */
/*返回值:无                                       */
/*-------------------------------------------------*/
void TempHumi_State(void)
{int humidity;           //定义一个变量,保存湿度值int temperature;        //定义一个变量,保存温度值int ch4;u16 TVOC_AD;int avalue;char temp[256]; u8 status;    //用于判断接收/发送状态u8 txbuf[4];    //发送缓冲u8 rxbuf[4];//接收缓冲u8 i;SPI_NRF_Init();u1_printf("\r\n   正在检测NRF与MCU是否正常连接。。。\r\n");status = NRF_Check(); /*等待接收数据*/if(status == SUCCESS)       u1_printf("\r\n      NRF与MCU连接成功!\r\n");  else    u1_printf("\r\n  正在检测NRF与MCU是否正常连接。。。\r\n"); u1_printf("\r\n 从机端 进入接收模式\r\n");NRF_RX_Mode();     //这边的是在收status = NRF_Rx_Dat(rxbuf);/*判断接收状态*/if(status == RX_DR){u1_printf("\r\n 从机端 接收到 主机端 发送的数据 \r\n");for(i=0;i<2;i++){   if(i%2==0){u1_printf("\r\n 温度的数据为:%d \r\n",rxbuf[i]);OLED_ShowNum(45,2,rxbuf[i],3,16);//显示温度的码值temperature=rxbuf[i];        //定义一个变量,保存温度值txbuf[i] =1;}else{u1_printf("\r\n 湿度的数据为:%d \r\n",rxbuf[i]);OLED_ShowNum(45,4,rxbuf[i],3,16);//显示湿度的码值humidity=rxbuf[i];          //定义一个变量,保存湿度值txbuf[i] =1;}TVOC_AD=Get_Adc_Average(ADC_Channel_0,4);OLED_ShowNum(0,6,TVOC_AD,4,16);//显示ADC的值avalue=(float)TVOC_AD*2*(3.3/4095);//测量值是在没有气体的环境下测得,同时测得的模值在进行这样的运算下是一个小数,又应为是avalue是一个int类型,所以值为0ch4=avalue;u1_printf("%.3dV--这个是烟雾数据",ch4);OLED_ShowNum(60,6,avalue,4,16);}                      }
//  DHT11_Read_Data(&temperature,&humidity);                   //读取温湿度值u1_printf("温度:%d  湿度:%d   甲醛:%d\r\n",temperature,humidity,ch4);  //串口输出信息sprintf(temp,"{\"method\":\"thing.event.property.post\",\"id\":\"203302322\",\"params\":{\"CurrentHumidity\":%d,\"Temperature\":%d,\"ch4\":%d},\"version\":\"1.0.0\"}",humidity,temperature,ch4);  //构建回复湿度温度数据MQTT_PublishQs0(P_TOPIC_NAME,temp,strlen(temp));   //添加数据,发布给服务器
}

三.踩坑处理

1.如果对整体的代码还不是非常熟悉的可以看看超纬电子STM32系列课程。
2.wifi模块在用之前就需要烧录设置为station模式
3.wifi的频段设置为2.4G
5.代码运用的二个串口,串口1用来串口输出,串口二用来上传数据到服务器
6.需要改动的地方时


7.如果使用的是这个代码,阿里云上面的产品设计需要设置的连接方式是蜂窝模式。

这里是代码下载地点
这个是我其他博客里面的资料

基于STM32和阿里云的矿道环境监测系统(温湿度DHT117,NRF2401(2.4G模块),气体传感器(MQ-3),0.96寸OLED屏,wifi模块)相关推荐

  1. 基于STM32的0.96寸OLED屏显示学号姓名和滚动显示

    文章目录 **一.SPI(串行外设接口)** **二.使用0.96寸OLED显示屏显示学号姓名** **三.0.96寸OLED在STM32f103上实现滚动显示长字符** **四.参考资料** 一.S ...

  2. 【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结

    目录 SPI版 OLED SPI 端口定义 七针OLED引脚定义 六针OLED引脚定义 软件SPI 硬件SPI 启用DMA 帧率测试 I2C 版 软件I2C 硬件I2C DMA STM32F103VE ...

  3. STM32 I2C驱动0.96寸OLED屏

    本文以STM32F103C8T6最小系统板为例               OLED屏为128*64像素  驱动芯片SSD1306 本文讲解标准库  硬件IIC和软件IIC 驱动OLED 硬件IIC ...

  4. 【STM32】HAL库在7针脚0.96寸OLED屏上的移植---硬件SPI(一)

    目录 SPI背景和接线 1.什么是SPI 2.如何接线 STM32CubeMX部分 1.配置时钟 2.配置SPI 3.工程生成 MDK 5 部分 1.移植OLED文件 2.修改引脚 3.修改main函 ...

  5. 用stm32f103c8t6点亮0.96寸oled屏(附带百度云例程)

    oled的技术文档中的例程好像时用keil4开发的,keil5打开时有问题,因此用自己建的c8t6工程做了移植,亲测有效. 首先挂出链接 链接:https://pan.baidu.com/s/19H5 ...

  6. STM32Mini基于SPI接口的0.96寸OLED屏数据显示

    文章目录 一.实验资料准备 1.下载工程包 2.引脚接法 3.字模软件准备 4.了解SPI(串行外设接口) (1)SPI的定义 (2)SPI的连接方式 (3)SPI的通讯过程 5.了解OLED屏的滚屏 ...

  7. 基于STM32和阿里云的环境检测系统设计

    一.主要实现功能 1.STM32采集温湿度,二氧化碳浓度在本地OLED进行数据显示 2.STM32通过串口将数据发送给ESP8266,然后将数据上传到阿里云 3.手机app进行远程查看数据+远程控制开 ...

  8. 基于STM32的0.96寸OLED显示屏显示数据和滚动显示

    文章目录 一.SPI 二.OLED显示屏显示数据 2.1 代码实现 2.2 结果展示 三.0.96寸OLED滚动显示数据 3.1 滚动方式 3.2 对显示文字进行取模 3.3 代码实现 3.4 结果展 ...

  9. 0.96寸OLED显示屏标准库移植HAL库(模拟IIC) - 基于STM32

    ** 0.96寸OLED显示屏标准库移植HAL库,使用模拟IIC ** 由于项目的需要使用OLED屏显示,并且现有的项目程序是基于HAL库编写的,而手头能找到的程序是标准库的驱动程序,大概看了一下代码 ...

最新文章

  1. ibmmq 通道命令_IBM MQ 使用指南
  2. OpenCASCADE:建模算法之将触感的形状连接起来
  3. boost::hana::plus用法的测试程序
  4. Silverlight学习笔记(三):创建第一个Silverlight应用程序
  5. 【Java语法】关于使用new和不使用new的数组值传递还是引用传递的问题
  6. 变化的和不变的-让自己慢下来(49)
  7. 邮件联系人,如何恕不部分字母就能显示邮件联系人
  8. jdk1.8 ::构造函数_在JDK 8中可通过反射获得构造函数/方法参数元数据
  9. api 二次 开发 禅道_二次开发
  10. 一步一步写算法(之排序二叉树)
  11. 通过axis2解析sap 发布的webService接口,新手到进阶,多种方法。
  12. python如何下载网易云付费音乐
  13. IT公司、软件公司资质
  14. linux下面如何看抓包文件,linux抓包
  15. PID解释与离散化算法公式
  16. Jpa是什么——Jpa使用详解
  17. ACI注册国际项目考试地点汇总
  18. SQL中drop,delete和truncate的异同
  19. linux ps命令什么意思,linux之ps命令详解
  20. Python使用opencv实现图片定位第三种方式

热门文章

  1. 计算机无法安装win2008,Win10系统安装不了VC++2008错误1935如何解决
  2. 使用struts2中的codebehind插件
  3. 跑通 可穿戴设备Samsung Gear Live
  4. 摄影技巧分享之:成功构图的要素
  5. 【SQL注入攻击介绍】
  6. note3升级android,三星Galaxy Note3的手机系统是什么?能升级安卓4.3吗?
  7. SequoiaDB实例管理
  8. Win7下无损分区和分区调整
  9. 递归中的return用法,逐级返回
  10. 雷达视频信号采集回放系统