作者:陈广
日期:2021-11-28
Wait_End_us
方法中,if(time > 1000) return -1;
这句代码应该放在while
循环内部,否则有可能因为长时间低电平或高电平导致程序待在此方法内无法返回。
//等待高电平或低电平结束,并返回持续时间
int Wait_End_us(uint32_t level)
{
SysTick->CTRL = 0;
SysTick->LOAD = US_TICK - 1;
SysTick->VAL = 0;
SysTick->CTRL = 5;
int time = 0;
while(DataPinIn == level)
{
while(!(SysTick->CTRL & 0x10000));
time++;
if(time > 1000) return -1;
}
SysTick->CTRL = 0;
return time;
}
注意:此代码为视频中的代码,其中错误请查看更正这一节。 dht11.c 文件源码:
/*
* dht11.c
*
* Created on: Nov 26, 2021
* Author: cg2021
*/
#include "dht11.h"
#include "bit_banding.h"
#include "stm32f1xx_ll_gpio.h"
#define DataPinOut PCout(3)
#define DataPinIn PCin(3)
#define HCLK 72000000
#define MS_TICK (HCLK / 1000)
#define US_TICK (HCLK / 1000000)
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
//将PC3设置为输出状态
void Set_GPIO_Output_State()
{
GPIO_InitStruct.Pin = LL_GPIO_PIN_3;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
//将PC3设置为输入状态
void Set_GPIO_Input_State()
{
GPIO_InitStruct.Pin = LL_GPIO_PIN_3;
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
void Delay_ms(uint32_t delay)
{
SysTick->CTRL = 0;
SysTick->LOAD = MS_TICK * delay - 1;
SysTick->VAL = 0;
SysTick->CTRL = 5;
while(!(SysTick->CTRL & 0x10000));
SysTick->CTRL = 0;
}
void Delay_us(uint32_t delay)
{
SysTick->CTRL = 0;
SysTick->LOAD = US_TICK * delay - 1;
SysTick->VAL = 0;
SysTick->CTRL = 5;
while(!(SysTick->CTRL & 0x10000));
SysTick->CTRL = 0;
}
//等待高电平或低电平结束,并返回持续时间
int Wait_End_us(uint32_t level)
{
SysTick->CTRL = 0;
SysTick->LOAD = US_TICK - 1;
SysTick->VAL = 0;
SysTick->CTRL = 5;
int time = 0;
while(DataPinIn == level)
{
while(!(SysTick->CTRL & 0x10000));
time++;
}
SysTick->CTRL = 0;
if(time > 1000) return -1;
return time;
}
/*
* 描述:读取DHT11的温湿度数据
* 参数:data 长度为5的uint8_t数组
* 返回值:
* 0:数据读取成功
* -1:响应信号低电平超时
* -2:响应信号高电平超时
* -3:数据读取错误
* -4:校验和错误
*/
int Dht11_Read(uint8_t data[])
{
Set_GPIO_Output_State();
DataPinOut = 0;
Delay_ms(20);
Set_GPIO_Input_State();
Delay_us(30);
//等待DHT11响应信号
if(Wait_End_us(0) < 0) return -1;
if(Wait_End_us(1) < 0) return -2;
//读取温湿度数据
int i, j;
for(i = 0; i < 5; i++)
{
uint8_t temp = 0;
for(j = 7; j >= 0; j--)
{
if(Wait_End_us(0) < 0) return -3;
Delay_us(40);
if(DataPinIn)
{
temp |= 1 << j;
Wait_End_us(1);
}
}
data[i] = temp;
}
uint8_t checksum = data[0]+data[1]+data[2]+data[3];
if(checksum != data[4]) return -4;
return 0;
}
;