回顾上一个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;//湿度最终结果