溧阳市建设局网站,电话用网站做综合布线,学校网站建立,房屋建筑学课程设计图纸文章目录 需求一、DHT11温湿度传感器二、模块配置流程1.配置时钟和IO2.读取数据3.数据处理 三、导入语音模块四、关键代码总结 需求
1.完成DHT11温湿度检测模块的配置。 2.处理DHT11获取的数据#xff0c;在串口打印处理后的实时数据。 2.通过Su-03t语音识别模块实现实时温湿… 文章目录 需求一、DHT11温湿度传感器二、模块配置流程1.配置时钟和IO2.读取数据3.数据处理 三、导入语音模块四、关键代码总结 需求
1.完成DHT11温湿度检测模块的配置。 2.处理DHT11获取的数据在串口打印处理后的实时数据。 2.通过Su-03t语音识别模块实现实时温湿度的问答。 一、DHT11温湿度传感器 DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件并与一个高性能 8 位单片机相连接。
引脚说明 1、VDD 供电 3.35.5V DC 2、DATA 串行数据单总线 3、NC 空脚 4、GND 接地电源负枀
二、模块配置流程
1.配置时钟和IO 由原理图可知该模块连接的是stm32的PG11引脚所以此时我们只需要配置PG11的引脚即可。 根据该模块手册中的数据时序图可知该引脚需要既能输入也能输出所以为了能够同时满足输入和输出我们将PG11引脚配置成开漏模式。 代码如下示例
void DHT11_Config()
{//配置为开漏模式//开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);//配置ioGPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_OD;GPIO_InitStruct.GPIO_Pin GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOG,GPIO_InitStruct);DHT11HIGH();
}配置完成后拉高电平是为了满足主机“拉高等待”状态。 为了方便后续操作先重定义一下拉高电平拉低电平和读操作。
#define DHT11HIGH() GPIO_SetBits(GPIOG,GPIO_Pin_11)#define DHT11LOW() GPIO_ResetBits(GPIOG,GPIO_Pin_11)#define DHT11read() GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)
2.读取数据
根据官方提供的外设读取步骤一步步进行操作即可 由图可知要先拉高电平 再拉低电平并持续18ms 再输出高电平然后用while检测83us的低电平应答信号。 收到应答信号后再用while检测87us的高电平外设准备接受信号。 接收到高电平外设准备接受信号后就可以接收40位的数据了。 直接定义一个数组进行for循环接收。 由于该模块发送的数据为高低电平信号并且是根据高电平持续时间的不同来判断究竟是高电平还是低电平此时我们只需要加个延迟比差值大 比74us小即可此处我用的是45us。
3.数据处理 由手册可知为了能够准确的将温湿度转换为10进制 此刻我们先用for循环将40个数据进行8位分组处理。 for(i0;i40;i){ //0~7 8~15 16~23 24~31 32~39data[i/8](arr[i](7-i%8));}分完组后在计算下和校验一下。 最后根据手册说明将16位数据转换为10进制并打印出来。
//根据DHT11时序读取数据
void DHT11_ReadData()
{uint16_t i 0;uint16_t timeout 0;uint8_t data[5] {0};uint8_t arr[50] {0};//输出一个最少18ms的低电平最大30msDHT11HIGH();DHT11LOW();Delay_nms(18);DHT11HIGH();//检测有持续83us低电平和87us的高电平timeout0;while(DHT11read()1)//检测83us低电平{timeout;Delay_nus(1);if(timeout100){return ;}}timeout0;while(DHT11read()0)//检测87us的高电平{timeout;Delay_nus(1);if(timeout100){return ;}}//读取40位数据for(i0;i40;i){timeout0;while(DHT11read()1)//等待us低电平{timeout;Delay_nus(1);if(timeout100){return ;}}timeout0;while(DHT11read()0)//等待能判断的高电平标志{timeout;Delay_nus(1);if(timeout100){return ;}}Delay_nus(45);arr[i]DHT11read();}for(i0;i40;i){ //0~7 8~15 16~23 24~31 32~39data[i/8](arr[i](7-i%8));}if(((data[0]data[1]data[2]data[3])0xff) ! data[4]){return;}humdata[0]data[1]/10.0;temdata[2](data[3]0x7f)/10.0;if((data[3]0x80) ! 0){tem 0-tem;}printf(读取完毕:湿度:%.1f 温度:%.1f\r\n,hum,tem);return;
}三、导入语音模块
先在su03t.c文件中外部声明一下处理后的温度和湿度。
extern float hum;
extern float tem;查看语音模块固件烧录时定义的指令找到湿度温度播报的指令 可以看到温度指令为06湿度指令为07。 最后将该数据和指令添加到int Su03tDealData()函数中就完成了。
四、关键代码
main.c
#include stm32f10x.h
#include usart.h
#include stdio.h
#include delay.h
#include kqm.h
#include string.h
#include su03t.h
#include dht11.hint main()
{NVIC_SetPriorityGrouping(5);//两位抢占两位次级Usart1_Config(); SysTick_Config(72000);Kqm_U4Config();Su03t_U5Config();DHT11_Config();while(1){ if(led2cnt[0]led2cnt[1]){//过去2sled2cnt[0]0;DHT11_ReadData();}KQM_DealData();Su03tDealData();}
}dht11.c
#include dht11.h
float hum,tem;
//PG11要能够切换输入输出
void DHT11_Config()
{//配置为开漏模式//开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);//配置ioGPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_OD;GPIO_InitStruct.GPIO_Pin GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOG,GPIO_InitStruct);DHT11HIGH();
}//根据DHT11时序读取数据
void DHT11_ReadData()
{uint16_t i 0;uint16_t timeout 0;uint8_t data[5] {0};uint8_t arr[50] {0};//输出一个最少18ms的低电平最大30msDHT11HIGH();DHT11LOW();Delay_nms(18);DHT11HIGH();//检测有持续83us低电平和87us的高电平timeout0;while(DHT11read()1)//检测83us低电平{timeout;Delay_nus(1);if(timeout100){return ;}}timeout0;while(DHT11read()0)//检测87us的高电平{timeout;Delay_nus(1);if(timeout100){return ;}}//读取40位数据for(i0;i40;i){timeout0;while(DHT11read()1)//等待us低电平{timeout;Delay_nus(1);if(timeout100){return ;}}timeout0;while(DHT11read()0)//等待能判断的高电平标志{timeout;Delay_nus(1);if(timeout100){return ;}}Delay_nus(45);arr[i]DHT11read();}for(i0;i40;i){ //0~7 8~15 16~23 24~31 32~39data[i/8](arr[i](7-i%8));}if(((data[0]data[1]data[2]data[3])0xff) ! data[4]){return;}humdata[0]data[1]/10.0;temdata[2](data[3]0x7f)/10.0;if((data[3]0x80) ! 0){tem 0-tem;}printf(读取完毕:湿度:%.1f 温度:%.1f\r\n,hum,tem);return;
}
dht11.h
#ifndef _DHT11_H_
#define _DHT11_H_
#include stm32f10x.h
#include delay.h
#include stdio.h
#include string.h
void DHT11_Config();
void DHT11_ReadData();#define DHT11HIGH() GPIO_SetBits(GPIOG,GPIO_Pin_11)#define DHT11LOW() GPIO_ResetBits(GPIOG,GPIO_Pin_11)#define DHT11read() GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11)#endif
su03t.c
#include stm32f10x.h
#include stdio.h
#include string.h
#include su03t.htypedef struct{uint8_t u5_recv[10];//保存数据数组uint8_t u5_cnt;//数组下标uint8_t u5_tflag;
}UART5DATA;//数据类型void Su03t_U5Config()//串口5 PC12TX PD2RX
{//开时钟U5 PD12TX PD2RXRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);//配置PC12TXGPIO_InitTypeDef GPIO_InitStruct {0};GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP;//复用推完输出GPIO_InitStruct.GPIO_Pin GPIO_Pin_12;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOC,GPIO_InitStruct);//PD2RXGPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_2;GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOD,GPIO_InitStruct);//配置串口5 波特率9600 数据位8校验位0停止位1USART_InitTypeDef USART_InitStruct {0};//可以通过结构体类型跳转USART_InitStruct.USART_BaudRate 9600;//波特率USART_InitStruct.USART_HardwareFlowControl USART_HardwareFlowControl_None;//硬件控制流不开USART_InitStruct.USART_Mode USART_Mode_Rx|USART_Mode_Tx;//打开接收USART_InitStruct.USART_Parity USART_Parity_No;USART_InitStruct.USART_StopBits USART_StopBits_1;USART_InitStruct.USART_WordLength USART_WordLength_8b;USART_Init(UART5,USART_InitStruct);//使能串口USART_Cmd(UART5,ENABLE);//配置串口4的中断(采用中断接收)USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);//使能串口4 的接收非空中断USART_ITConfig(UART5,USART_IT_IDLE,ENABLE);//总线空闲中断NVIC_SetPriority(UART5_IRQn,6);//设置优先级0~15NVIC_EnableIRQ(UART5_IRQn);//使能中断通道
}//串口5发送单字节函数
void Uart5Senddata(uint8_t data)
{//等待发送完成while(USART_GetFlagStatus(UART5,USART_FLAG_TC)0);//如果上次发送完成就发送USART_SendData(UART5,data);
}//串口5发送数组函数
void U5_Sendarr(uint8_t * data,uint32_t len)
{uint32_t i0;for(i0;ilen;i){Uart5Senddata(*data);data;}
}UART5DATA u5_data{0};
void UART5_IRQHandler()//串口5中断执行
{uint8_t data0;//判断接收中断是否发生if(USART_GetITStatus(UART5,USART_IT_RXNE)SET){data UART5-DR;//USART1-DR data;//回显u5_data.u5_recv[u5_data.u5_cnt]data;u5_data.u5_cnt;u5_data.u5_cnt%10;}//触发空闲中断表示总线空闲接收完毕if(USART_GetITStatus(UART5,USART_IT_IDLE)SET){data UART5-SR;//清理空闲中断先读SR再读DRdata UART5-DR; u5_data.u5_tflag1;}
}//将double转换成8位类型数组arr
void DoubleToUint8(double data,uint8_t *arr)
{uint8_t *p (uint8_t *)data;uint8_t i0;for(i0;i8;i){arr[i]p[i];printf(%02x ,*(pi));}printf(\r\n);return;
}extern float voc;
extern float ch2o;
extern float co2;
extern float hum;
extern float tem;int Su03tDealData()
{if(u5_data.u5_tflag!1){return 1;}if(u5_data.u5_recv[0]!0xAA||u5_data.u5_recv[1]!0x55){printf(数据帧头出错\r\n);return 2;}if(u5_data.u5_recv[4]!0xAA||u5_data.u5_recv[3]!0x55){printf(数据帧尾出错\r\n);return 3;} switch(u5_data.u5_recv[2]){case 1:printf(接收01空气质量指令\r\n);Su03tSendMsg(1,voc);//vocbreak;case 2: printf( 接收02甲醛指令\r\n);Su03tSendMsg(2,ch2o);//vocbreak;case 3: printf( 接收03Co2指令\r\n);Su03tSendMsg(3,co2);//vocbreak;case 6: printf( 接收06温度指令\r\n);Su03tSendMsg(6,tem);break;case 7: printf( 接收07湿度指令\r\n);Su03tSendMsg(7,hum);break;}memset(u5_data,0,sizeof(u5_data));return 0;
}//拼接指令函数 AA 55 04 00 00 00 00 00 80 37 40 55 AA
void Su03tSendMsg(uint8_t cmd,double data)
{uint8_t msg[13]{0};//存放要发送的指令msg[0]0xAA;msg[1]0x55;msg[2]cmd;DoubleToUint8(data,msg[3]);msg[11]0x55;msg[12]0xAA;//通过串口5发送U5_Sendarr(msg,13);
}
su03t.h
#ifndef _SU03T_H_
#define _SU03T_H_
#include stm32f10x.h
void Su03t_U5Config();
void Uart5Senddata(uint8_t data);
void U5_Sendarr(uint8_t * data,uint32_t len);
void UART5_IRQHandler();
void DoubleToUint8(double data,uint8_t *arr);
int Su03tDealData();
void Su03tSendMsg(uint8_t cmd,double data);
#endif 总结
1.先根据原理图和该模块的手册配置对应的时钟和io。 2.进行数据读取严格按照该模块手册中的时序一步一步来。 3.最后进行数据处理并导入到语音模块。