介绍
温湿度模块DHT11和DHT22小项目用得比较多,虽然二者均是1-wire协议,但是细节部分还是有所差异。1-wire协议我就不多介绍了,网上很详细。这里着重介绍二者使用的区别。
DHT11
DHT22
DHT系列区别
DHT11和DHT22
芯片手册
提取:hgew
起始信号
DHT11
DHT22
显然DHT11拉低要>18ms,而DHT22拉低只要>1ms就足够。
代码实现
/*
* 一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
DHT11_Dout_0;
/*延时18ms*/
DHT11_DELAY_MS(18); //dht11
//DHT11_DELAY_MS(2); //dht22
/*总线拉高 主机延时30us*/
DHT11_Dout_1;
DHT11_DELAY_US(30); //延时30us
/*主机设为输入 判断从机响应信号*/
DHT11_Mode_IPU();
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(DHT11_Dout_IN()==Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(DHT11_Dout_IN()==Bit_RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(DHT11_Dout_IN()==Bit_SET);
/*开始接收数据*/
DHT11_Data->humi_int= DHT11_ReadByte();
DHT11_Data->humi_deci= DHT11_ReadByte();
DHT11_Data->temp_int= DHT11_ReadByte();
DHT11_Data->temp_deci= DHT11_ReadByte();
DHT11_Data->check_sum= DHT11_ReadByte();
/*读取结束,引脚改为输出模式*/
DHT11_Mode_Out_PP();
/*主机拉高*/
DHT11_Dout_1;
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return SUCCESS;
else
return ERROR;
}
else
return ERROR;
}
13行
DHT11_DELAY_MS(18);
14行DHT11_DELAY_MS(2);
//DHT11时,延时18ms;DHT22时,延时1ms(建议2ms,经测试1ms有可能读取失败)
数据处理
DHT11
DHT22
代码实现
/*
* 一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
uint32_t humi=0;
uint32_t temp =0;
/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
DHT11_Dout_0;
/*延时2ms*/
DHT11_DELAY_MS(2);
/*总线拉高 主机延时30us*/
DHT11_Dout_1;
DHT11_DELAY_US(30); //延时30us
/*主机设为输入 判断从机响应信号*/
DHT11_Mode_IPU();
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(DHT11_Dout_IN()==Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(DHT11_Dout_IN()==Bit_RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(DHT11_Dout_IN()==Bit_SET);
/*开始接收数据,需要修改的计算方式跟dht11不同*/
DHT11_Data->humi_int= DHT11_ReadByte();
DHT11_Data->humi_deci= DHT11_ReadByte();
DHT11_Data->temp_int= DHT11_ReadByte();
DHT11_Data->temp_deci= DHT11_ReadByte();
DHT11_Data->check_sum= DHT11_ReadByte();
/*读取结束,引脚改为输出模式*/
DHT11_Mode_Out_PP();
/*主机拉高*/
DHT11_Dout_1;
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
{ /*----------------------------------数据处理-----------------------*/
/*----------------DHT22温湿度16bit精度,故需要分高低字节计算,且需要uint32_t变量装载---------------------*/
/*-----------------------------湿度和温度的高八位需要乘以256再加上低八位---------------------------------*/
humi = DHT11_Data->humi_int *256 + DHT11_Data->humi_deci;
temp = DHT11_Data->temp_int *256 + DHT11_Data->temp_deci;
DHT11_Data->humi_int = (uint8_t)(humi*0.1);
DHT11_Data->humi_deci = humi%10;
DHT11_Data->temp_int = (uint8_t)(temp*0.1);
DHT11_Data->humi_deci = temp%10;
return SUCCESS;
}
else
return ERROR;
}
else
return ERROR;
}
此处并没有错,我的程序通过
改变宏定义
即可切换dht11或dht22测量。所以函数名称没改回来。
调试问题
DHT22读取失败
1.主机拉低发送起始信号延时1ms时会读取失败,但延时2ms能完美解决问题。
2.两次数据读取时间过短,建议大于2s。