1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 基于STM32的实时温湿度 蜂鸣器控制系统(温湿度 光敏数据上传 onenet(MQTT))

基于STM32的实时温湿度 蜂鸣器控制系统(温湿度 光敏数据上传 onenet(MQTT))

时间:2024-03-12 04:42:45

相关推荐

基于STM32的实时温湿度 蜂鸣器控制系统(温湿度 光敏数据上传 onenet(MQTT))

一、开发环境搭建

云品台:onenet

协议支持:MQTT

硬件部署:STM32F407 ESP8266 DHT11 光敏传感器

二、部分源码展示(源程序太多了,MQTT协议支持和部分函数没有出现在这)

1.main:

RTC_TimeTypeDef RTC_TimeStruct;RTC_DateTypeDef RTC_DateStruct;unsigned short timeCount = 0;//发送间隔变量unsigned char *dataPtr = NULL; u8 t=0;u8 tbuf[40];NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168); //初始化延时函数uart_init(115200);//初始化串口波特率为115200UsartPrintf(USART_DEBUG, " system running\r\n");usart3_Init(115200);LED_Init();//初始化LED LCD_Init();//LCD初始化 BEEP_Init();My_RTC_Init(); //初始化RTCLsens_Init(); //初始化光敏传感器POINT_COLOR=RED;//设置字体为红色 RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits,0);//配置WAKE UP中断,1秒钟中断一次while(DHT11_Init())//DHT11初始化{LCD_ShowString(30,130,200,16,16,"DHT11 Error");delay_ms(200);LCD_Fill(30,130,239,130+16,WHITE);delay_ms(200);} LCD_Clear(WHITE);LCD_ShowString(30,30,200,16,16,"DHT11 OK");LCD_ShowString(30,50,200,16,16,"NETWORK CONNECTINGING");LCD_ShowString(30,70,200,16,16,"Please wait...");ESP8266_Init();//初始化ESP8266UsartPrintf(USART_DEBUG," Hardware init OK\r\n");delay_ms(500);while(1){if(t%10==0)//每100ms读取一次{DHT11_Read_Data(&temperature,&humidity);//读取温湿度值 LCD_ShowNum(30+40,190,temperature,2,16);//显示温度LCD_ShowNum(30+40,210,humidity,2,16);//显示湿度 adcx=Lsens_Get_Val();LCD_ShowxNum(30+10*8,150,adcx,3,16,0);//显示ADC的值 RTC_GetTime(RTC_Format_BIN,&RTC_TimeStruct);sprintf((char*)tbuf,"Time:%02d:%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes,RTC_TimeStruct.RTC_Seconds); LCD_ShowString(30,90,210,16,16,tbuf);RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);sprintf((char*)tbuf,"Date:20%02d-%02d-%02d",RTC_DateStruct.RTC_Year,RTC_DateStruct.RTC_Month,RTC_DateStruct.RTC_Date); LCD_ShowString(30,110,210,16,16,tbuf);sprintf((char*)tbuf,"Week:%d",RTC_DateStruct.RTC_WeekDay); LCD_ShowString(30,130,210,16,16,tbuf);} delay_ms(10);t++;if(t==20){t=0;LED0=!LED0;}if(++timeCount >= 500)//发送间隔5s{UsartPrintf(USART_DEBUG, "OneNet_SendData\r\n");OneNet_SendData();//发送数据timeCount = 0;ESP8266_Clear();}dataPtr = ESP8266_GetIPD(0);if(dataPtr != NULL)OneNet_RevPro(dataPtr);delay_ms(10);}

uart3:

```c*************************************************************函数名称:UsartPrintf**函数功能:格式化打印**入口参数:USARTx:串口组*fmt:不定长参**返回参数:无**说明:************************************************************```cvoid Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len){unsigned short count = 0;for(; count < len; count++){USART_SendData(USARTx, *str++);//发送数据while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);//等待发送完成}}*************************************************************函数名称:UsartPrintf**函数功能:格式化打印**入口参数:USARTx:串口组*fmt:不定长参**返回参数:无**说明:************************************************************void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...){unsigned char UsartPrintfBuf[296];va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);//格式化va_end(ap);while(*pStr != 0){USART_SendData(USARTx, *pStr++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);}}

Lsens:

//初始化光敏传感器void Lsens_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟//先初始化ADC3通道7IO口GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//PA7 通道7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//不带上下拉GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 Adc3_Init();//初始化ADC3}//读取Light Sens的值//0~100:0,最暗;100,最亮 u8 Lsens_Get_Val(void){u32 temp_val=0;u8 t;for(t=0;t<LSENS_READ_TIMES;t++){temp_val+=Get_Adc3(ADC_Channel_5);//读取ADC值,通道5delay_ms(5);}temp_val/=LSENS_READ_TIMES;//得到平均值 if(temp_val>4000)temp_val=4000;return (u8)(100-(temp_val/40));}

adc:

void Adc3_Init(void){ADC_CommonInitTypeDef ADC_CommonInitStructure;ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能ADC3时钟RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE); //ADC3复位RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);//复位结束 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz ADC_CommonInit(&ADC_CommonInitStructure);//初始化ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 ADC_Init(ADC3, &ADC_InitStructure);//ADC初始化ADC_Cmd(ADC3, ENABLE);//开启AD转换器 } //获得ADC值//ch:通道值 0~16 ADC_Channel_0~ADC_Channel_16//返回值:转换结果u16 Get_Adc3(u8 ch) {//设置指定ADC的规则组通道,一个序列,采样时间ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_480Cycles );//ADC3,ADC通道,480个周期,提高采样时间可以提高精确度 ADC_SoftwareStartConv(ADC3);//使能指定的ADC3的软件转换启动功能while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADC3);//返回最近一次ADC3规则组的转换结果}

WIFI:

void ESP8266_Init(void){GPIO_InitTypeDef GPIO_Initure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟//ESP8266复位引脚GPIO_Initure.GPIO_Mode = GPIO_Mode_OUT; //PF6GPIO_Initure.GPIO_OType=GPIO_OType_PP;GPIO_Initure.GPIO_Pin = GPIO_Pin_6;//复位GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOF, &GPIO_Initure);GPIO_WriteBit(GPIOF, GPIO_Pin_6, Bit_RESET);delay_ms(250);GPIO_WriteBit(GPIOF, GPIO_Pin_6, Bit_SET);delay_ms(500);ESP8266_Clear();UsartPrintf(USART_DEBUG, " 1. AT\r\n");while(ESP8266_SendCmd("AT\r\n", "OK"))delay_ms(500);UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))delay_ms(500);UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))delay_ms(500);UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))delay_ms(500);UsartPrintf(USART_DEBUG, "5. CIPSTART\r\n");while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))delay_ms(500);UsartPrintf(USART_DEBUG, "6. ESP8266 Init OK\r\n");}

//==========================================================//函数名称:ESP8266_SendData////函数功能:发送数据////入口参数:data:数据//len:长度////返回参数:无////说明://==========================================================void ESP8266_SendData(unsigned char *data, unsigned short len){char cmdBuf[32];ESP8266_Clear();//清空接收缓存sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);//发送命令if(!ESP8266_SendCmd(cmdBuf, ">"))//收到‘>’时可以发送数据{Usart_SendString(USART3, data, len);//发送设备连接请求数据}}//==========================================================//函数名称:ESP8266_GetIPD////函数功能:获取平台返回的数据////入口参数:等待的时间(乘以10ms)////返回参数:平台返回的原始数据////说明:不同网络设备返回的格式不同,需要去调试//如ESP8266的返回格式为"+IPD,x:yyy"x代表数据长度,yyy是数据内容//==========================================================unsigned char *ESP8266_GetIPD(unsigned short timeOut){char *ptrIPD = NULL;do{if(ESP8266_WaitRecive() == REV_OK)//如果接收完成{ptrIPD = strstr((char *)esp8266_buf, "IPD,");//搜索“IPD”头if(ptrIPD == NULL)//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间{//UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");}else{ptrIPD = strchr(ptrIPD, ':');//找到':'if(ptrIPD != NULL){ptrIPD++;return (unsigned char *)(ptrIPD);}elsereturn NULL;}}delay_ms(5);//延时等待} while(timeOut--);return NULL;//超时还未找到,返回空指针}

//==========================================================//函数名称:USART3_IRQHandler////函数功能:串口3收发中断////入口参数:无////返回参数:无////说明://==========================================================void USART3_IRQHandler(void){if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断{if(esp8266_cnt >= sizeof(esp8266_buf))esp8266_cnt = 0; //防止串口被刷爆esp8266_buf[esp8266_cnt++] = USART3->DR;USART_ClearFlag(USART3, USART_FLAG_RXNE);}}

//==========================================================//函数名称:ESP8266_Clear////函数功能:清空缓存////入口参数:无////返回参数:无////说明://==========================================================void ESP8266_Clear(void){memset(esp8266_buf, 0, sizeof(esp8266_buf));esp8266_cnt = 0;}//==========================================================//函数名称:ESP8266_WaitRecive////函数功能:等待接收完成////入口参数:无////返回参数:REV_OK-接收完成REV_WAIT-接收超时未完成////说明:循环调用检测是否接收完成//==========================================================_Bool ESP8266_WaitRecive(void){if(esp8266_cnt == 0) //如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return REV_WAIT;if(esp8266_cnt == esp8266_cntPre)//如果上一次的值和这次相同,则说明接收完毕{esp8266_cnt = 0;//清0接收计数return REV_OK;//返回接收完成标志}esp8266_cntPre = esp8266_cnt;//置为相同return REV_WAIT;//返回接收未完成标志}//==========================================================//函数名称:ESP8266_SendCmd////函数功能:发送命令////入口参数:cmd:命令//res:需要检查的返回指令////返回参数:0-成功1-失败////说明://==========================================================_Bool ESP8266_SendCmd(char *cmd, char *res){unsigned char timeOut = 200;Usart_SendString(USART3, (unsigned char *)cmd, strlen((const char *)cmd));while(timeOut--){if(ESP8266_WaitRecive() == REV_OK)//如果收到数据{if(strstr((const char *)esp8266_buf, res) != NULL)//如果检索到关键词{ESP8266_Clear();//清空缓存return 0;}}delay_ms(10);}return 1;}

onenet:

//==========================================================//函数名称:OneNet_DevLink////函数功能:与onenet创建连接////入口参数:无////返回参数:1-成功0-失败////说明:与onenet平台建立连接//==========================================================_Bool OneNet_DevLink(void){MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};//协议包unsigned char *dataPtr;_Bool status = 1;UsartPrintf(USART_DEBUG, "OneNet_DevLink\r\n""PROID: %s,AUIF: %s,DEVID:%s\r\n", PROID, AUTH_INFO, DEVID);if(MQTT_PacketConnect(PROID, AUTH_INFO, DEVID, 256, 0, MQTT_QOS_LEVEL0, NULL, NULL, 0, &mqttPacket) == 0){ESP8266_SendData(mqttPacket._data, mqttPacket._len);//上传平台dataPtr = ESP8266_GetIPD(250);//等待平台响应if(dataPtr != NULL){if(MQTT_UnPacketRecv(dataPtr) == MQTT_PKT_CONNACK){switch(MQTT_UnPacketConnectAck(dataPtr)){case 0:UsartPrintf(USART_DEBUG, "Tips:连接成功\r\n");status = 0;break;case 1:UsartPrintf(USART_DEBUG, "WARN:连接失败:协议错误\r\n");break;case 2:UsartPrintf(USART_DEBUG, "WARN:连接失败:非法的clientid\r\n");break;case 3:UsartPrintf(USART_DEBUG, "WARN:连接失败:服务器失败\r\n");break;case 4:UsartPrintf(USART_DEBUG, "WARN:连接失败:用户名或密码错误\r\n");break;case 5:UsartPrintf(USART_DEBUG, "WARN:连接失败:非法链接(比如token非法)\r\n");break;default:UsartPrintf(USART_DEBUG, "ERR:连接失败:未知错误\r\n");break;}}}MQTT_DeleteBuffer(&mqttPacket);//删包}elseUsartPrintf(USART_DEBUG, "WARN:MQTT_PacketConnect Failed\r\n");return status;}unsigned char OneNet_FillBuf(char *buf){char text[32];dht11_info.temperature=temperature;dht11_info.humidity=humidity;beep_info.beep=BEEP;lesnes_info.adcx=adcx;memset(text, 0, sizeof(text));strcpy(buf, ",;");memset(text, 0, sizeof(text));sprintf(text, "Beep,%d;", beep_info.beep);strcat(buf, text);memset(text, 0, sizeof(text));sprintf(text, "Temprature,%f;", dht11_info.temperature);strcat(buf, text);memset(text, 0, sizeof(text));sprintf(text, "Humidity,%f;", dht11_info.humidity);strcat(buf, text);memset(text, 0, sizeof(text));sprintf(text, "LSENS_VAL:,%f;", lesnes_info.adcx);strcat(buf, text);return strlen(buf);}//==========================================================//函数名称:OneNet_SendData////函数功能:上传数据到平台////入口参数:type:发送数据的格式////返回参数:无////说明://==========================================================void OneNet_SendData(void){MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};//协议包char buf[128];short body_len = 0, i = 0;UsartPrintf(USART_DEBUG, "Tips:OneNet_SendData-MQTT\r\n");memset(buf, 0, sizeof(buf));body_len = OneNet_FillBuf(buf);//获取当前需要发送的数据流的总长度if(body_len){if(MQTT_PacketSaveData(DEVID, body_len, NULL, 5, &mqttPacket) == 0)//封包{for(; i < body_len; i++)mqttPacket._data[mqttPacket._len++] = buf[i];ESP8266_SendData(mqttPacket._data, mqttPacket._len);//上传数据到平台UsartPrintf(USART_DEBUG, "Send %d Bytes\r\n", mqttPacket._len);MQTT_DeleteBuffer(&mqttPacket);//删包}elseUsartPrintf(USART_DEBUG, "WARN:EDP_NewBuffer Failed\r\n");}}//==========================================================//函数名称:OneNet_RevPro////函数功能:平台返回数据检测////入口参数:dataPtr:平台返回的数据////返回参数:无////说明://==========================================================void OneNet_RevPro(unsigned char *cmd){MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};//协议包char *req_payload = NULL;char *cmdid_topic = NULL;unsigned short req_len = 0;unsigned char type = 0;short result = 0;char *dataPtr = NULL;char numBuf[10];int num = 0;type = MQTT_UnPacketRecv(cmd);switch(type){case MQTT_PKT_CMD://命令下发result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len);//解出topic和消息体if(result == 0){UsartPrintf(USART_DEBUG, "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len);if(MQTT_PacketCmdResp(cmdid_topic, req_payload, &mqttPacket) == 0)//命令回复组包{UsartPrintf(USART_DEBUG, "Tips:Send CmdResp\r\n");ESP8266_SendData(mqttPacket._data, mqttPacket._len);//回复命令MQTT_DeleteBuffer(&mqttPacket);//删包}}break;case MQTT_PKT_PUBACK://发送Publish消息,平台回复的Ackif(MQTT_UnPacketPublishAck(cmd) == 0)UsartPrintf(USART_DEBUG, "Tips:MQTT Publish Send OK\r\n");break;default:result = -1;break;}ESP8266_Clear();//清空缓存if(result == -1)return;dataPtr = strchr(req_payload, '}');//搜索'}'if(dataPtr != NULL && result != -1)//如果找到了{dataPtr++;while(*dataPtr >= '0' && *dataPtr <= '9')//判断是否是下发的命令控制数据{numBuf[num++] = *dataPtr++;}numBuf[num] = 0;num = atoi((const char *)numBuf);//转为数值形式//处理平台下发命令if(strstr((char *)req_payload, "BEEP")){if(num == 1){BEEP=1;//add your code here}else if(num == 0){BEEP=0;//add your code here}}}if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH){MQTT_FreeBuffer(cmdid_topic);MQTT_FreeBuffer(req_payload);}}

程序部分来源网络其他博主作为参考

三、界面展示

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。