DHT21/AM2301 数字温湿度传感器
DHT21/AM2301 数字温度传感器模块只有三根线,VCC(红),DATA(黄),GND(黑)。VCC 接 3.3V 供电,DATA 为数字电平输出,直接接数字 I/O 口即可
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的数据,并触发一次信号采集
空闲时总线为高电平,通讯开始时主机拉低总线 1~10ms 后释放总线,延时20-40us后主机开始检测从机(DHT21)的响应信号。
从机的响应信号是一个 80us 左右的低电平,随后从机在拉高总线80us左右代表即将进入数据传送。
高电平后就是数据位,每 1bit 数据都是由一个低电平时隙和一个高电平组成。低电平时隙就是一个 50us 左右的低电平,它代表数据位的起始,其后的高电平的长度决定数据位所代表的数值,较长的高电平代表 1,较短的高电平代表 0。共 40bit 数据,当最后一Bit数据传送完毕后,从机将再次拉低总线 50us 左右,随后释放总线,由上拉电阻拉高。
则撰写测试驱动为:
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); }