DHT21/AM2301 数字温湿度传感器

来自Jack's Lab
跳转到: 导航, 搜索

DHT21/AM2301 数字温度传感器模块只有三根线,VCC(红),DATA(黄),GND(黑)。VCC 接 3.3V 供电,DATA 为数字电平输出,直接接数字 I/O 口即可

DH21.png

DHT21/AM2301 数字温度传感器使用单总线串行接口,完整的湿度温度数据是 40 位;


读时高位先出,每次读一位,连续读取 40bit,其中高 16 位是湿度,中间 16 位是温度,后 8 位是校验数据:

0000 0010 1000 1100 | 0000 0001 0101 1111 | 1110 1110 湿度数据 温度数据 校验和


其中校验和应为: 湿度高8位 + 湿度低8位 + 温度高8位 + 温度低8位

例如:0000 0010 + 1000 1100 + 0000 0001 + 0101 1111 = 1110 1110

上面的数值表示:湿度 = 65.2%RH 温度 = 35.1℃


当温度低于0℃时温度数据的最高位置 1

例如:-10.1℃表示为1000 0000 0110 0101


主机发送一次开始信号后,DHT21从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT21发送响应信号,送出40bit的数据,并触发一次信号采集


DH21-bus-1.jpg



空闲时总线为高电平,通讯开始时主机拉低总线 1~10ms 后释放总线,延时20-40us后主机开始检测从机(DHT21)的响应信号。

从机的响应信号是一个 80us 左右的低电平,随后从机在拉高总线80us左右代表即将进入数据传送。


DH21-bus-2.jpg



高电平后就是数据位,每 1bit 数据都是由一个低电平时隙和一个高电平组成。低电平时隙就是一个 50us 左右的低电平,它代表数据位的起始,其后的高电平的长度决定数据位所代表的数值,较长的高电平代表 1,较短的高电平代表 0。共 40bit 数据,当最后一Bit数据传送完毕后,从机将再次拉低总线 50us 左右,随后释放总线,由上拉电阻拉高。


DH21-bus-3.jpg


DH21-bus-4.jpg


则撰写测试驱动为:


int dataPin = 12;
int flag = 0;
byte temp, RH_H, RH_L, T_H, T_L, crc;
int tt, rh;

byte read_8bit_data()
{
  byte i, data = 0;
  for(i = 0; i < 8; i++)
  {
    flag = 2;
    while((digitalRead(dataPin) == 0) && flag++);
    delayMicroseconds(30);
    temp = 0;
    if(digitalRead(dataPin) == 1) temp = 1;
    flag = 2;
    while((digitalRead(dataPin) == 1) && flag++);
    if(flag == 1) break;
    data <<= 1;
    data |= temp;
  }
  return data;
}

byte get_dh21()
{
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, LOW);
  delay(4);

  digitalWrite(dataPin, HIGH);
  delayMicroseconds(40);

  pinMode(dataPin, INPUT);
  if(digitalRead(dataPin) == 0)
  {
    flag = 2;
    while((digitalRead(dataPin) == 0) && flag++);
    flag = 2;
    while((digitalRead(dataPin) == 1) && flag++);
    RH_H = read_8bit_data();
    RH_L = read_8bit_data();
    T_H = read_8bit_data();
    T_L = read_8bit_data();
    crc = read_8bit_data();
    pinMode(dataPin, OUTPUT);
    digitalWrite(dataPin,HIGH);
    temp = (T_H + T_L + RH_H + RH_L);
    if(temp != crc)
    {
        RH_H = 0;
        RH_L = 0;
        T_H = 0;
        T_L = 0;
        return -1;
    }
    return 0;
  }
  return -1;
}

void setup()
{
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  Serial.begin(9600);
}

void loop()
{
  if(get_dh21() == -1)
  {
    Serial.println("Read DH21 error");
  }
  else
  {
    tt = (T_H << 8 ) | T_L;
    rh = (RH_H << 8 ) | RH_L;
    Serial.print("Current Temperature: ");
    Serial.print(tt, DEC);
    Serial.print("C   ");
    Serial.print("Current Humidity: ");
    Serial.print(rh);
    Serial.println("%");
  }
  delay(60000*5);
}














个人工具
名字空间

变换
操作
导航
工具箱