基于LPC11C14芯片的DHT11温湿度传感器的使用

作者:杨老师,华清远见教育科技集团讲师。

DHT11传感器的产品特性:

数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。传感器包括一个电阻式感湿元件和一个 NTC测温元件,幵与一个高性能 8 位单片机相连接。具有成本低、长期稳定、相对湿度和温度测量、 品质卓越、超快响应、抗干扰能力强、 超长的信号传输距离、数字信号输出、精确校准等特性。

DHT11与MCU的电路连接图:

DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。一次传送 40 位数据,高位先出,包含32位数据位和8位校验位。

DHT11的数据读取时序图:

DHT11的数据‘0’和‘1’表示:

读取数据:

在LPC11C14芯片上使用PIO1_5引脚来进行控制传输数据,读取数据需要根据时序图来发送信号。

主机发送发送起始信号示例代码:

LPC_GPIO[1]->DIR |= 1<<5; //将PIO1_5引脚设为电平输出
        LPC_GPIO[1]->MASKED_ACCESS[(1<<5)] = (0<< 5);//将PIO1_5的电平拉低
        LPC_GPIO[1]->MASKED_ACCESS[(1<<5)] = (1<< 5);//将PIO1_5的电平拉高
        delay_ms(30);// 延时30ms

从机发送响应信号:有时序得出从机响应信号为一个低电平和一个高电平,这里通过PIO1_5的三次边沿中断来进行判断。

GPIOSetInterrupt(PORT1, 5, 0, 0, 0);//将PIO1_5设置为下降沿触发中断,实现为以下4行

(LPC_GPIO1->IS &= ~(0x1<<5);
        LPC_GPIO1->IBE &= ~(0x1<<5);
        LPC_GPIO1->IEV &= ~(0x1<<5);
        LPC_GPIO1->IE |= (0x1<<5);)

for(i=0; i<3; i++)
        {
        GPIOSetInterrupt(PORT1, 5, 0, 0, i&0x01);//根据次数来设置上升沿或者下降沿触发中断
        while(p3_2_counter == cnt_last); //在没有触发中断时停在此处
        cnt_last = p3_2_counter;
        }// 触发了三次中断之后主机得到了从机的响应信号

for(i=0; i<40; i++)// 读取40位数据
        {
        GPIOSetInterrupt(PORT1, 5, 0, 0, 1);// 设置为上升沿触发
        while(p3_2_counter == cnt_last);
        cnt_last = p3_2_counter;
        tc1 = p3_2_tc;// 此处的p3_2_tc的值为系统滴答SysTick->VAL的值。
        GPIOSetInterrupt(PORT1, 5, 0, 0, 0);// 设置为下降沿触发
        while(p3_2_counter == cnt_last);
        cnt_last = p3_2_counter;
        if(p3_2_tc < tc1)
        {
        tc = tc1 - p3_2_tc;// 判断两次中断的时间差
        }
        else
        {
        tc = 48000 - (p3_2_tc - tc1);// 判断两次中断的时间差
        }
        if(i < 8)
        {
        hum_10 <<= 1;
        if(tc >= 2328)// 通过时间差是否在数据‘1’的范围内。
        hum_10 |= 0x01;
        }
        else if(i < 16) // two byte
        {
        hum_01 <<= 1;
        if(tc >= 2328)
        hum_01 |= 0x01;
        }
        else if(i < 24) // three byte
        {
        temp_10 <<= 1;
        if(tc >= 2328)
        temp_10 |= 0x01;
        }
        else if(i < 32) // four byte
        {
        temp_01 <<= 1;
        if(tc >= 2328)
        temp_01 |= 0x01;
        }
        else // five byte checksum
        {
        chksum <<= 1;
        if(tc >= 2328)
        chksum |= 0x01;
        }
        }
        GPIOSetInterrupt(PORT1, 5, 0, 0, 1);
        while(p3_2_counter == cnt_last);// 结束信号
        GPIOIntDisable(PORT1, 5);
        *temp = temp_10;
        *(temp+1) = temp_01;
        *hum = hum_10;
        *(hum+1) = hum_01;
        chk = hum_10;
        chk += hum_01;
        chk += temp_10;
        chk += temp_01; // 进行校验判断