完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
dht11简易获取温湿度数据
DHT11数据格式 采集范围:温度0-50°±2°,湿度:20-90%RH。 精度:湿度±5%RH, 温度±2℃ 采用单总线双向串行通信协议,每次采集都要由单片机发起开始信号,然后DHT11会向单片机发送响应并开始传输40位数据帧。 如接收到的 40 位数据为: 0011 0101 0000 0000 0001 1000 0000 0100 0101 0001 湿度高 8 位 湿度低 8 位 温度高 8 位 温度低 8 位 校验位 校验位为“8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据” 8bit 校验位等于所得结果的末 8 位 校验计算: 0011 0101+0000 0000+0001 1000+0000 0100= 0101 0001 则接收数据正确 湿度: 0011 0101(整数)=35H=53%RH 0000 0000(小数)=00H=0.0%RH =>53%RH + 0.0%RH = 53.0%RH 温度: 0001 1000(整数)=18H=24℃ 0000 0100(小数)=04H=0.4℃ =>24℃ + 0.4℃ = 24.4℃ DHT11时序: 时序流程详解: 1.主机把总线拉低大于18ms,保证DHT11能检测。 2.主机拉高等待延时20us-40us。 3.DHT11若有响应,会返回给主机低电平接近80us,即响应信号。 4.DHT11返回给主机高电平80us,准备发送数据给主机。 5.发送的数据每1bit之间间隙为50us,当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。 数据格式 发送的数据如何判断为0还是1呢,由发送时高电平的持续时长决定。 检测高电平为70us,即为1. 检测高电平为26us-28us,即为0 硬件连接 本实验以PA1连接DHT11的DQ引脚 部分代码 按照之前的时序详解来说明: 时序流程一,二步: 1 void DHT11_Rst(void) { DHT11_IO_OUT(); //设置GPIOA1为输出 DHT11_DQ_Low; //DQ=0 delay_ms(20); //拉低至少18ms DHT11_DQ_High; //DQ=1 delay_us(30); //主机拉高20~40us } 时序流程三,四步: u8 DHT11_Check(void) { u8 retry=0;//定义临时变量 DHT11_IO_IN();//SET INPUT while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//DHT11会拉低40~80us { retry++; printf("%s %dn",__FUNCTION__,__LINE__);//方便在串口中观察错误是否DHT11未响应 delay_us(1); }; if(retry>=100)return 1; //并无响应 else retry=0;//有响应 while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; //拉高过久还未发送数据给主机 return 0; } 时序流程第五部,读取一位: 1 u8 DHT11_Check(void) { u8 retry=0;//定义临时变量 DHT11_IO_IN();//SET INPUT while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//DHT11会拉低40~80us { retry++; printf("%s %dn",__FUNCTION__,__LINE__);//方便在串口中观察错误是否DHT11未响应 delay_us(1); }; if(retry>=100)return 1; //并无响应 else retry=0;//有响应 while ((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; //拉高过久还未发送数据给主机 return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1)&&retry<100)//等待变为低电平,数据间隙 { retry++; delay_us(1); } retry=0; while((GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==0)&&retry<100)//等待变高电平,数据 { retry++; delay_us(1); } delay_us(40);//等待40us if(GPIO_ReadInputDataBit(GPIO_DHT11,IO_DHT11)==1) return 1; //若还为高电平,数据为1 else return 0; //数据为0 } 读取一字节函数: 1 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); //8位 } return dat; //返回8位 } 读取一次数据函数,校验并存储数据道buf中: u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); //时序流程一,二步。 if(DHT11_Check()==0) //有响应 { for(i=0;i<5;i++)//读取40位数据 { buf=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) //校验成功 { *humi=buf[0]; //湿度高16位 *temp=buf[2]; // 温度的16位 } } else return 1; //失败 return 0; //成功 } 各类初始化: void DHT11_Init(void) { DHT11_Rst(); //复位DHT11 DHT11_Check();//等待DHT11的回应 } 还有初始化PA1位模拟输入和推挽输出的函数,就不列出了 DHT11_IO_IN();//设置输入 DHT11_IO_OUT();//设置输出 main 1 int main { u8 wd=0; u8 sd=0; DHT11_Init(); USART1_config(115200); while(1) { DHT11_Read_Data(&wd,&sd);//读取温湿度值 printf("temp = %d humi =%dn",wd,sd); delay_ms(1000); delay_ms(1000); } } 结果 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1632 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1559 浏览 1 评论
985 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1605 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
655浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
525浏览 3评论
540浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
512浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 18:06 , Processed in 1.357161 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号