关于DHT11的数据获取
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数
字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一
个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。(摘自官方的描述)
废话不多说,直接看时序图
整体介绍,
当一次开始之后,DHT11会发生40bit的信号,一共5个字节,计算方式如下
外设读取步骤
步骤一:
DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境
温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的
DATA 引脚处于输入状态,时刻检测外部信号。
步骤二:
微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms),
然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变
高,等待 DHT11 作出回答信号,发送信号如图所示:
(摘自官方的描述)
步骤三:
DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA
引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒
的高电平后的数据接收,发送信号如图所示:
(摘自官方的描述)
/*在这里我将步骤二和步骤三写在一起了*/
static void usDelay(uint8_t x) //毫秒延迟,我开了一个定时器,但是我没有开中断,会有一点误差,但是不会太大
{
LL_TIM_DisableCounter(TIM1);
LL_TIM_SetCounter(TIM1, 0);
LL_TIM_EnableCounter(TIM1);
while (LL_TIM_GetCounter(TIM1) != x)
{
}
}
static uint8_t SetDHT11(void)
{
uint8_t wait = 0;
LL_GPIO_SetPinMode(GPIOB,LL_GPIO_PIN_1,LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinOutputType(GPIOB,LL_GPIO_PIN_1,LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_1);
LL_mDelay(19); //根据描述,拉低大于18MS
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_1);
usDelay(30); //释放总线
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_1, LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_1, LL_GPIO_OUTPUT_OPENDRAIN);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_1, LL_GPIO_PULL_UP); //将引脚置为输入
while ((!LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1)) && (wait < 100))
{
wait++;
usDelay(1);
}
if (wait > 99)
return 0;
else //判断是否有83us的低电平,考虑到各方面的误差,我放到了<99
{
wait = 0;
while ((LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1)) && (wait < 100))
{
usDelay(1);
wait++;
}
if (wait > 99) //判断是否有87us的高电平,考虑到各方面的误差,我放到了<99
{
wait = 0;
return 0;
}
else
return 1;
}
}
步骤四:
由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”
的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74
微秒的高电平。位数据“0”、“1”格式信号如图所示:
(摘自官方的描述)
/*在这里我做了整合,直接得到一个字节的数据*/
static uint8_t ReadDHT11_Byte(void)
{
uint8_t wait;
uint8_t value_bit;
uint8_t value;
for (uint8_t n = 0; n < 8; n++)
{
if (!LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1))
{
while (!LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1) && (wait < 65))
{
wait++;
usDelay(1);
} //等待共同的低电平
wait = 0;p
usDelay(40); //判断下一个时刻的电平
if (LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1))
value_bit = 1; //都>27us了一定为1
else
value_bit = 0;
value <<= 1; //移位
value |= value_bit;
while (LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_1) && (wait < 27)) //等待剩下的高电平
{
wait++;
usDelay(1);
}
}
}
return value;
}