DHT11数字温 湿度传感器 是一款含有已校准 数字信号 输出的温湿度复合 传感器 。其成本低、长期稳定、可以测量相对湿度和温度测量,并可以只使用一根数据线进行温湿度采集。
模块实物展示:
资料下载 链接: 资料 提取码:2sgq
2. 规格 参数
模块的厂家资料下载见百度网盘链接
工作电压:3-5.5V
工作 电流 :1MA
测量分辨率:8 bit
湿度量程: 20 - 90 %RH
湿度精度:±5 %RH
温度量程: 0 - 50 ℃
温度精度:±2 ℃
通信 协议:单总线
管脚数量:3n(2.54mm间距 排针 )
3.移植过程
我们的目标是在立创·地文星·CW32F030C8T6开发板上实现读取温湿度的功能。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
3.1查看资料
DHT11使用的是单总线通信,即发送数据与接收数据都在一根数据线上,通过规定的时序进行控制。
从左向右看,时序一开始,主机 信号 就保持着高电平,所以引脚初始化完毕时,及时给引脚输出高电平。因为 模块的数据线要求空闲时,要保持高电平状态。(其实模块上已经接了上拉 电阻 ,使数据线一直保持高电平)
根据时序图可以知道,主机(开发板)发送一次开始信号,待主机开始信号结束后,DHT11 发送响应信号,送出 温湿度数据,并触发一次数据采集给下一次数据读取作准备。因此完成一次数据读取需要进行起始信号、响应信号、数据接收、结束信号。
读取数据步骤:
起始信号:主机(开发板)接入数据线的I/O输出低电平,且低电平保持时间不能小于 18ms
DATA_GPIO_OUT(0);//数据线输出低电平delay_1ms(19);//起始信号保持时间19msDATA_GPIO_OUT(1);//主机释放总线delay_uus( 20 );//拉高等待
2.响应信号:等待模块的响应信号到来。将数据线改为输入模式,如果接入到低电平,说明接收到模块的响应。
DHT11_GPIO_Mode_IN();//数据线转为输入模式//如果前面没有错误,则模块会发出低电平的应答信号,//所以直接等待DHT11拉高,83usmeout = 5000;while( (! alt="wKgaombezDCAPKz1AAAOIPxofP859.webp">#define CHECK_TIME 28 //超过0值的高电平时间f(i=0;i<40;i++)//循环接收40位数据{timeout = 5000;//等待低电平过去while( ( !DATA_GPIO_IN ) && (timeout > 0) ) timeout--; //54usdelay_uus(CHECK_TIME);//等待超过位数据0值的高电平时间if ( alt="wKgaombezDGAWixvAAAD0rhXYR424.webp">DHT11_GPIO_Mode_OUT();//转为输出模式DATA_GPIO_OUT(1);//主机释放总线数据接收完成,但是这40位数据要如何转化为温湿度数据?并如何保证传输的数据没有错误?
DHT11模块一次完整的数据传输为40bit,高位先出。数据格式:
8bit湿度整数数据 + 8bit湿度小数数据 + 8bi温度整数数据 + 8bit温度小数数据 + 8bit校验和
注意
湿度小数部分数据一直为0。
数据传送正确时,校验和数据等于“8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据”所得结果的末8位。举几个例子。
示例一:接收的40位数据分别为:
湿度高8位 | 湿度低8位 | 温度高8位 | 温度低8位 | 校验位 |
校验和为 0011 0101 + 0000 0000 + 0001 1000 + 0000 0100 = 0101 0001,与接收的数据一致
湿度为 0011 0101 + 0000 0000 = 35 + 0 = 35%RH
温度为 0001 1000 0000 0100 = 24 + 4 = 24.4℃
示例二:接收的40位数据分别为:
湿度高8位 | 湿度低8位 | 温度高8位 | 温度低8位 | 校验位 |
校验和为 0011 0101 + 0000 0000 + 0001 1000 + 0000 0100 = 0101 0001,与接收的数据不一致 计算的数据为0101 0001,接收的数据为0100 1001,两者不一致说明数据不准确,丢弃这次数据,重新接收。
以下为数据处理的实现代码:
//val为接收到的40位数据。//湿高8+ 湿低8+ 温高8+ 温低8verify_num = (val>>32) + (val>>24) + (val>>16) + (val>>8);//计算的校验和 与 接收的校验和 的差为0说明一致,不为0说明不一致//(val&0xff)是因为val的大小为64位,我们只需要val的最后8位校验和verify_num = verify_num - (val&0xff);//进行校验if( verify_num )//如果不为0,说明校验失败{//校验错误return 0;}else //校验成功{//数据处理humidity = (val>>32)&0xff;//湿度前8位(小数点前数据)small_point = (val>>24)&0x00ff;//湿度后8位(小数点后数据)small_point = small_point * 0.1;//换算为小数点humidity = humidity + small_point; //小数前+小数后printf("湿度:%.2frn",humidity);mperature = (val>>16)&0x0000ff;//温度前8位(小数点前数据)small_point = (val>>8)&0x000000ff; //温度后8位(小数点后数据)small_point = small_point * 0.1;//换算为小数点temperature = temperature + small_point;//小数前+小数后printf("温度:%.2frn",temperature);return val>>8; //返回未处理的数据}
3.2引脚选择
该模块有3个引脚,具体引脚连接见 表 各引脚连接。
3.3移植至工程
工程模板下载请查看入门手册百度链接
然后我们打开空白工程,新建两个文件dht11.c和dht11.h
在文件dht11.c中,编写如下代码。
/* * Change Logs: * DateAuthorNotes * 2024-06-19LCKFB-LPfit version */#include "dht11.h"#include "stdio.h"float temperature = 0;float humidity = 0;/****************************************************************** * 函 数 名 称:DHT11_GPIO_Init * 函 数 说 明:DHT11温湿度传感器初始化 * 函 数 形 参:无 * 函 数 返 回:无 * 作者:LC * 备注:无******************************************************************/void DHT11_GPIO_Init(void){GPIO_InitTypeDefGPIO_InitStruct; // GPIO初始化结构体RCC_DHT11_GPIO_ENABLE();// 使能GPIO时钟GPIO_InitStruct.Pins = GPIO_DHT11;// GPIO引脚GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;// 推挽输出GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;// 输出速度高GPIO_Init(PORT_DHT11, &GPIO_InitStruct);// 初始化DATA_GPIO_OUT(1);}/****************************************************************** * 函 数 名 称:DHT11_GPIO_Mode_OUT * 函 数 说 明:配置DHT11的数据引脚为输出模式 * 函 数 形 参:无 * 函 数 返 回:无 * 作者:LC * 备注:无******************************************************************/void DHT11_GPIO_Mode_OUT(void){GPIO_InitTypeDefGPIO_InitStruct; // GPIO初始化结构体GPIO_InitStruct.Pins = GPIO_DHT11;// GPIO引脚GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;// 推挽输出GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;// 输出速度高GPIO_Init(PORT_DHT11, &GPIO_InitStruct);// 初始化}/****************************************************************** * 函 数 名 称:DHT11_GPIO_Mode_IN * 函 数 说 明:配置DHT11的数据引脚为输入模式 * 函 数 形 参:无 * 函 数 返 回:无 * 作者:LC * 备注:无******************************************************************/void DHT11_GPIO_Mode_IN(void){GPIO_InitTypeDefGPIO_InitStruct; // GPIO初始化结构体GPIO_InitStruct.Pins = GPIO_DHT11;// GPIO引脚GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP;// 上拉输入GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;// 输出速度高GPIO_Init(PORT_DHT11, &GPIO_InitStruct);// 初始化}/****************************************************************** * 函 数 名 称:DHT11_Re_Data * 函 数 说 明:根据时序读取温湿度数据 * 函 数 形 参:无 * 函 数 返 回:0=数据校验失败其他=温湿度未处理的数据 * 作者:LC * 备注:无******************************************************************/unsigned int DHT11_Read_Data(void){int i;long long val=0;int timeout=0;float small_point=0;unsigned char verify_num = 0;//验证值DATA_GPIO_OUT(0);//数据线输出低电平delay_ms(19);//起始信号保持时间19msDATA_GPIO_OUT(1);//主机释放总线delay_us( 20 );//拉高等待DHT11_GPIO_Mode_IN();//数据线转为输入模式//如果前面没有错误,则模块会发出低电平的应答信号,所以直接等待DHT11拉高,80ustimeout = 5000;while( (! target="_blank">.h"#include "dht11.h"int32_t main(void){board_init();// 开发板初始化uart1_init(115200);// 串口1波特率115200DHT11_GPIO_Init();//DHT11引脚初始化delay_ms(1000);printf("DHT11 demo startrn");while(1){//读取模块数据DHT11_Read_Data();//显示读取后的温度数据printf("temperature = %.2frn", Get_temperature() );//显示读取后的湿度数据printf("humidity = %.2frn", Get_humidity() );delay_ms(1000);}}
上电效果:
模块移植成功案例代码:
链接:提取码:LCKF审核编辑 黄宇