第九篇,温湿度传感器(DHT11)编程

1.原理图

DHT11使用单总线通信,使用一根数据线进行传输,再加上VCC,GND,闲置接口(NC),一共四根线。

数据线连接到了CPU的PG9,外接上拉电阻。

2.查看DHT11的说明手册了解其如何工作

 数据格式:

通信时序:

CPU发送起始信号 ===> DTH11响应起始信号 ===> DHT11发回温湿度数据

(1)CPU发送起始信号和模块响应

(2)如何传输1位数据

 

3.代码实现

(1)起始信号和模块响应

说明一下这段代码的写法:

//等待拉低
    while(DQ_IN&&retry<100){
        retry++;
        delay_us(1);
    }
    if(retry>=100)//如果没有拉低,无响应
        return 1;

逻辑或&&:表达式1 || 表达式2 || 表达式3...如果表达式1的运算结果为true,则整个表达式的结果为true,同时不会再执行后面的表达式,如果表达式1的运算结果为false,则根据表达式2的运算结果继续判断。

逻辑与||:表达式1 && 表达式2 && 表达式3...如果表达式1的运算结果为false,则整个表达式的结果为false,同时不会再执行后面的表达式,如果表达式1的运算结果为true,则根据表达式2的运算结果继续判断。
 

(2)读一位数据

(3)读取温湿度

//读1字节数据,高位先出
u8 dht11_read_byte(void)
{
	u8 i,dat = 0;
	
	//连续读取8位
	for(i=0;i<8;i++){
		dat |= dht11_read_bit()<<(7-i);
	}
	
	return dat;
}

//读取温湿度数据
//返回0表示成功,非0表示失败
//temp和humi是输出参数,输出温湿度
u8 dht11_read_data(u8 *temp,u8 *humi)
{
	u8 i,buf[5];
	
	//起始信号
	if(dht11_check()==0){
		//读取40bit数据
		for(i=0;i<5;i++){
			buf[i] = dht11_read_byte();
		}
		//验证校验和
		if(((buf[0]+buf[1]+buf[2]+buf[3])&0xff)==buf[4]){
			*humi = buf[0];
			*temp = buf[2];
			
			return 0;
		}
	}
	
	return 1;
}

//代码实现

#include <stm32f4xx.h>
#include <dht11.h>
#include <delay.h>

//配置DQ 输入模式/输出模式
void dht11_set_io(GPIOMode_TypeDef IO)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	//1.开启GPIOG的时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);
	
	//2.GPIO初始化 PG9
	GPIO_InitStruct.GPIO_Mode = IO;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	GPIO_Init(GPIOG,&GPIO_InitStruct);
}

//测试dht11是否有响应,返回0表示正常,非0表示无响应
u8 dht11_check(void)
{
	u32 retry = 0;
	
	//输出模式
	dht11_set_io(GPIO_Mode_OUT);
	//发送>18ms低电平起始信号
	DQ_OUT = 0;
	//保持20ms
	delay_ms(20);
	DQ_OUT = 1;
	
	//等待20~40us
	delay_us(30);
	
	//输入模式
	dht11_set_io(GPIO_Mode_IN);
	
	//等待拉低
	while(DQ_IN&&retry<100){
		retry++;
		delay_us(1);
	}
	if(retry>=100)//如果没有拉低,无响应
		return 1;
	
	retry = 0;
	//80us后拉高
	while(!DQ_IN&&retry<100){
		retry++;
		delay_us(1);
	}
	if(retry>=100)//如果没有拉高,无响应
		return 1;
	
	return 0;
}

//读1位数据
u8 dht11_read_bit(void)
{
	u32 retry = 0;
	
	//等待变为低电平,80us
	while(DQ_IN&&retry<100){
		retry++;
		delay_us(1);
	}
	if(retry>=100)//如果没有拉低,无响应
		return 100;
	
	retry = 0;
	//等待拉高,50us
	while(!DQ_IN&&retry<100){
		retry++;
		delay_us(1);
	}
	if(retry>=100)//如果没有拉高,无响应
		return 100;
	
	//延时40us,读取电平 低电平 ----- 0  高电平 ----- 1
	delay_us(40);
	return DQ_IN;
}

//读1字节数据,高位先出
u8 dht11_read_byte(void)
{
	u8 i,dat = 0;
	
	//连续读取8位
	for(i=0;i<8;i++){
		dat |= dht11_read_bit()<<(7-i);
	}
	
	return dat;
}

//读取温湿度数据
//返回0表示成功,非0表示失败
//temp和humi是输出参数,输出温湿度
u8 dht11_read_data(u8 *temp,u8 *humi)
{
	u8 i,buf[5];
	
	//起始信号
	if(dht11_check()==0){
		//读取40bit数据
		for(i=0;i<5;i++){
			buf[i] = dht11_read_byte();
		}
		//验证校验和
		if(((buf[0]+buf[1]+buf[2]+buf[3])&0xff)==buf[4]){
			*humi = buf[0];
			*temp = buf[2];
			
			return 0;
		}
	}
	
	return 1;
}

基于温度湿度一体的传感器DHT11 以下是在51单片机上测试成功的代码 #include<at89x52.h> #include<intrins.h>//加上这句下面的 _nop_();就能用 bit xianshiqiehuan; // sbit dht11_dat=P1^6; //开发板用 sbit dht11_dat=P2^0; //使用版用 unsigned char c,count, dht11temp,dht11dat; unsigned char dht11value[5]; unsigned int x,y,z; unsigned char code dat[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,}; delay() { unsigned char a; for(a=200;a>0;a--); } display(unsigned char x) //使用版用 { P0=dat[(x0)/10];//十位 P2_3=0; delay(); P2_3=1; P0=dat[(x0)];//个位 P2_2=0; delay(); P2_2=1; } /*display(unsigned char x) //开发板用 { P0=dat[(x0)/10];//十位 P1_2=0; delay(); P1_2=1; P0=dat[(x0)];//个位 P1_3=0; delay(); P1_3=1; } */ delay_1s() { unsigned int i=50000; while(i--); } delay_10us() //10us { _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); } void delayms(unsigned char x) //1ms单位延时程序 { unsigned char j; while(x--) { for(j=0;j<123;j++){;} } } read_dht11() { unsigned char i; dht11_dat=1; _nop_(); //起始 dht11_dat=0;//拉低总线 delayms(18);//手册要求大于18ms dht11_dat=1;//拉高总线等待dht11回应 while(dht11_dat); // 等待dht11回应 若有回应 dht11_dat=0;往下执行 while(!dht11_dat);//回应后dht11将总线拉低80us,过后又将总线拉高,进入下一步 while(dht11_dat); //拉高80us 又变低,往下执行 进入50us延时 for(i=0;i<24;i++) { while(!dht11_dat);//50us过后...... dht11_dat=1;往下执行 delay_10us();delay_10us();delay_10us();//延时30us,查看总线是高是低, dht11temp=0; //先默认为0处理 if(dht11_dat) dht11temp=1; //1处理 dht11dat=dht11dat<<1; //必须先移动再或 若先或再移本次数据就移动了 dht11dat=dht11dat|dht11temp; dht11value[i/8]=dht11dat; while(dht11_dat);//如果处理的是1,30us过后总线还是1,那就在此等待总线变为0进入下一个50us低电平,不然会重复进行0处理 } } main() { delay_1s(); //要求上电等1秒,让dht11稳定 EA=1;//开放中断 TMOD=0x01;//设T0 为16位计数方式 ET0=1;//定时0中断允许 TR0=1;//开启TR0 while(1) { if(!xianshiqiehuan) //显示温度 display(dht11value[2]) ; else {display(dht11value[0]) ; //显示湿度 P0=0x92&0x7f; //千位显 S.代表湿度 P2_5=0; delay(); P2_5=1; } } } dingshi() interrupt 1 //定时器0服务程序 { TH0=0; TL0=0; count++; if(count==55){count=0;read_dht11();xianshiqiehuan=~xianshiqiehuan; } //在切换显示时采集,以防中断采样带来的显示闪烁 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值