首页 LMVE论坛 资讯 插画 时光机 我的社区 用户 搜索

[HAL库]DHT11温湿度传感器更好的驱动

无闻风
发表于 2019-08-08 11:29:26
3
201

回顾上一个dht11的温湿度传感器驱动,有很多可以优化的地方。

DHT11温湿度传感器数据读取。

比如:完全可以不用定时器,因为上次没注意到,每个bit前都有一个50us的下拉信号,可以用这个下拉信号作为时间基准。

先定一个变量time_a,对1Bit开始信号计数,再定一个time_b对上拉信号计数,最后判断time_b是否大于time_a,如果是说明这个Bit是1否则为0.

代码:

定义一些变量

struct							
{
	unsigned char rh;	//濕度整數
	unsigned char rhdot;	//濕度小數
	unsigned char t;	//溫度整數
	unsigned char tdot;	//溫度小數
	unsigned char sum;	//用於驗證數據是否正確的
}dh11;				//定義溫濕度數據的結構體

设置引脚输入或者输出

void dht11_in_or_out(char a)//0in  1out			//設置引腳輸入輸出
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = dht11_Pin;
	if(a==0)
	{
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	}
	if(a==1)
	{
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	}
	HAL_GPIO_Init(dht11_GPIO_Port, &GPIO_InitStruct);
}

主功能函数

char get_dht11_data2()
{
	char b;
	long long_time=0;
	unsigned int time_a=0,time_b=0;
	dht11_in_or_out(1);			//引腳設置為輸出
	set_dh11_pin(0);			//下拉引腳 使模塊進入高速模式
	HAL_Delay(20);				//數據手冊說明需要延時20ms
	set_dh11_pin(1);			//拉高引腳
	dht11_in_or_out(0);			//設置為輸入 開始接收數據
	long_time=HAL_GetTick()+10;		//設置10ms內完成讀取  防止while卡死

	while(read_dh11_pin==1){if(HAL_GetTick()>long_time){return 0;}}     //等待模塊返回一個下降沿  如果等待超時會直接彈出函數 返回0
	while(read_dh11_pin==0){if(HAL_GetTick()>long_time){return 0;}}	    //第一個數據是模塊的開始傳輸標誌  這個數據直接略過
	while(read_dh11_pin==1){if(HAL_GetTick()>long_time){return 0;}}
	for(b=0;b<8;b++)				        			//正式開始接收數據一共5個字節 第一個數據 8位
	{
	    while(read_dh11_pin==0){time_a++;if(HAL_GetTick()>long_time){return 0;}}	//等待總線被拉高,并且对基准计时
	    while(read_dh11_pin==1){time_b++;if(HAL_GetTick()>long_time){return 0;}}	//總線被拉低,并且计时拉低时间
	    dh11.rh<<=1;								//先高位 所以向左移(就是这里,先左移)動
	    if(time_b>time_a)							        //讀取時間 如果時間大於40us 
	    {
		dh11.rh|=0x01;						                //說明這一位數據是1  給到最低位(再或操作)
	    }
			time_a=0;
			time_b=0;
	}
	for(b=0;b<8;b++)
	{
	    while(read_dh11_pin==0){time_a++;if(HAL_GetTick()>long_time){return 0;}}
	    while(read_dh11_pin==1){time_b++;if(HAL_GetTick()>long_time){return 0;}}
            dh11.rhdot<<=1;
	    if(time_b>time_a)
            {
		dh11.rhdot|=0x01;
	    }
	    time_a=0;
	    time_b=0;
	}
	for(b=0;b<8;b++)
	{
	    while(read_dh11_pin==0){time_a++;if(HAL_GetTick()>long_time){return 0;}}
	    while(read_dh11_pin==1){time_b++;if(HAL_GetTick()>long_time){return 0;}}
            dh11.t<<=1;
	    if(time_b>time_a)
	    {
		dh11.t|=0x01;
	    }
	    time_a=0;
	    time_b=0;
	}
	for(b=0;b<8;b++)
	{
	    while(read_dh11_pin==0){time_a++;if(HAL_GetTick()>long_time){return 0;}}
	    while(read_dh11_pin==1){time_b++;if(HAL_GetTick()>long_time){return 0;}}
            dh11.tdot<<=1;
	    if(time_b>time_a)
	    {
		dh11.tdot|=0x01;
	    }
	    time_a=0;
	    time_b=0;
	}
	for(b=0;b<8;b++)		                        //接收最後一個數據  這個是驗證字節
	{
	    while(read_dh11_pin==0){time_a++;if(HAL_GetTick()>long_time){return 0;}}
	    while(read_dh11_pin==1){time_b++;if(HAL_GetTick()>long_time){return 0;}}
            dh11.sum<<=1;	
	    if(time_b>time_a)
	    {
	        dh11.sum|=0x01;
	    }	
	    time_a=0;
	    time_b=0;
	}			
	if(dh11.sum==0)                                        //如果验证为0也是错误数据
	{
	    return 0;
	}else
	{
	    if(dh11.sum==dh11.rh+dh11.rhdot+dh11.t+dh11.tdot) //根據數據手冊  最後一個字節如果等於前四個字節相加,數據就是正確的
	    {
		return 1;                                     //数据正确返回1
	    }	
	}
    return 0;
}

使用方法:

每1.5S调用一次上面的函数char get_dht11_data2()

如果返回1

进行数据处理

数据处理

float rh,temp;
temp=dh11.t+(float)dh11.tdot/10;//温度最终结果
rh=dh11.rh+(float)dh11.rhdot/10;//湿度最终结果

最后修改 2019-08-14 20:26:21
3
201
用户评论 (3)
一起折腾