一、引脚说明
二、时序解读
2.1、通信过程
2.2、开始信号
主机发送一个大于18ms的低电平给DHT11作为启动信号。
然后拉高20-40us后读DHT11响应信号。
发开始信号
DHT11_IO_OUT(); //SET OUTPUT
DHT11_OUT_LOW(); //拉低DQ
delay_ms(5); //拉低至少18ms
delay_ms(5);
delay_ms(5);
delay_ms(5);
DHT11_OUT_HIGH(); //DQ=1
delay_us(30); //主机拉高20~40us
2.3、响应信号
DHT11检测到开始信号后,会等待开始信号结束,然后发送响应信号。
响应信号为一个80us的低电平。
响应信号发送后,会拉高80us,然后发送数据。
读响应信号
DHT11_IO_IN();//SET INPUT
while (DHT11_IN_LEVEL() == 0 && retry<100)//DHT11会拉低80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 0;
else retry=0;
2.4、一位数据的表示
一个位数据总是从50us的低电平开始,高电平持续时间不同表示0和1
2.4.1、数字0信号
高电平持续26-28us表示0
2.4.2、数字1信号
高电平持续70us表示0
2.4.3、读取一位数据
低电平结束后,延时大于28us(小于28+50us,要在下一个高电平来之前读取数据),主机读取当前电平,读到高电平表示DHT11发送数据1,读到低电平表示DHT11发送数据0。
while(DHT11_IN_LEVEL())//等待变为低电平
{
}
while(!DHT11_IN_LEVEL())//等待变高电平
{
}
delay_us(40);//等待40us
return DHT11_IN_LEVEL();
三、树莓派4B内核驱动代码(部分代码)
使用GPIO25
#define delay_us(x) udelay(x);
#define delay_ms(x) mdelay(x);
#define DHT11_IO_OUT() *GPFSEL2 &= ~(0x6 << 15);\
*GPFSEL2 |= (0x1 << 15);
#define DHT11_IO_IN() *GPFSEL2 &= ~(0x7 << 15);\
*GPFSEL2 |= (0x0 << 15);
#define DHT11_OUT_HIGH() *GPSET0 = 1 << 25;
#define DHT11_OUT_LOW() *GPCLR0 = 1 << 25;
#define DHT11_IN_LEVEL() ((*GPLEV0>>25) & 1)
static unsigned char DHT11_Read_Bit(void)
{
while(DHT11_IN_LEVEL())//等待变为低电平
{
}
while(!DHT11_IN_LEVEL())//等待变高电平
{
}
delay_us(40);//等待40us
return DHT11_IN_LEVEL();
}
//从DHT11读取一个字节
static unsigned char DHT11_Read_Byte(void)
{
unsigned char i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
static unsigned char DHT11_Read_Data(unsigned char *temp,unsigned char *humi)
{
unsigned char buf[5];
unsigned char i;
unsigned char retry=0;
DHT11_IO_OUT(); //SET OUTPUT
DHT11_OUT_LOW(); //拉低DQ
delay_ms(5); //拉低至少18ms
delay_ms(5);
delay_ms(5);
delay_ms(5);
DHT11_OUT_HIGH(); //DQ=1
delay_us(30); //主机拉高20~40us
DHT11_IO_IN();//SET INPUT
while (DHT11_IN_LEVEL() == 0 && retry<100)//DHT11会拉低80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 0;
else retry=0;
if(retry==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 0;
return 1;
}
四、测试代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
char data[2];
int nread = 0;
int fd = open("/dev/dht11",O_RDWR);
if(fd == -1){
perror("open ");
exit(-1);
}
while(1){
getchar();
nread = read(fd,data,2);
printf("nread :%d temp=%d humi=%d\n",nread,data[0],data[1]);
}
}