没想到蓝桥杯官方资料更新到四梯官网了,今天才下到今年的国赛资源包
目录
一. 原理
1.初始化
2.DHT11_Check
3.数据采集
二. 代码编写
1. dht11.c文件
2. dht.h文件
3. main.c 文件
三. 注意事项
结语
一. 原理
从代码入手,按代码运行顺序来解释一下
1.初始化
设置引脚为输出模式,并且拉高电平,高电平表示为总线空闲
2.DHT11_Check
当DHT11接收到单片机的开始信号(拉低电平)后,等待单片机开始信号结束,然后发送80us低电平响应信号。
单片机拉高电平表示开始信号结束,单片机需延时等待20-40us后,
切换为输入模式。等待单片机发的高电平转成DHT11的80us低电平信号,再等待低电平结束,返回0,表示可以开始采集数据。
3.数据采集
首先要等待上一步的高电平结束,然后低电平能才开始判断数据是0还是1。
数据0和1都可以分为两部分,前面一部分都是50us的低电平,只有后面的高电平时间不一样。为了更加方便写代码,可以利用数据0和1在这个地方的时间差,等过了28us,电平是低电平就是数据0,反之是1。所以会加一个延时。
数据0的时序图:
数据1的时序图:
二. 代码编写
1. dht11.c文件
#include "dht11_hal.h"
dht11Data dht11;
//
static void usDelay(uint32_t us)
{
uint16_t i = 0;
while(us--){
i = 30;
while(i--);
}
}
//
void outDQ(uint8_t i)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = HDQ;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
if(!i)
HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_SET);
}
//
void inDQ(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = HDQ;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//
uint8_t DHT11_Check(void)
{
uint8_t re = 0;
inDQ();//设置为输入
while (HAL_GPIO_ReadPin(GPIOA, HDQ) && re < 100) //DHT11会拉低40~80us
{
re++;
usDelay(1);
};
if(re >= 100)return 1;
else re = 0;
while (!HAL_GPIO_ReadPin(GPIOA, HDQ) && re < 100) //DHT11拉低后会再次拉高40~80us
{
re++;
usDelay(1);
};
if(re >= 100)return 1;
return 0;
}
//
void dht11Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
outDQ(1); //空闲状态高电平
}
//
uint8_t recData(void)
{
uint8_t i,temp=0;
for(i=0; i<8; i++){
while(HAL_GPIO_ReadPin(GPIOA,HDQ)&&n<100)
{
n++;
usDelay(1);
};
while(!HAL_GPIO_ReadPin(GPIOA,HDQ)&&m<100)
{
m++;
usDelay(1);
}; //等待低电平结束
usDelay(40); //卡时间
if(HAL_GPIO_ReadPin(GPIOA,HDQ))
{
temp=(temp<<1)|1;
}
else
{
temp=(temp<<1)|0;
}
n=0;
m=0;
}
return temp;
}
void DHT11_Read_Data(float *temp, float *humi)
{
uint8_t buf[5];
uint8_t i;
outDQ(0);
HAL_Delay(20); //拉低至少18ms
HAL_GPIO_WritePin(GPIOA, HDQ, GPIO_PIN_SET); //高电平
usDelay(30); //主机拉高20~40us
if(DHT11_Check() == 0)
{
for(i = 0; i < 5; i++)
{
buf[i] = recData();
}
if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0]+buf[1]/10.f;
*temp = buf[2]+buf[3]/10.f;
}
}
}
2. dht.h文件
#ifndef __DHT11_HAL_H
#define __DHT11_HAL_H
#include "stm32g4xx_hal.h"
#define HDQ GPIO_PIN_7
typedef struct {
uint8_t humidity_high;
uint8_t humidity_low;
uint8_t temperature_high;
uint8_t temperature_low;
}dht11Data;
void dht11Init(void);
//dht11Data* dht11Read(void);
void DHT11_Read_Data(float *temp, float *humi);
#endif
3. main.c 文件
需要的可以参考这一篇:蓝桥杯嵌入式——扩展板DHT11_☆时光の星阵☆的博客-CSDN博客
记得改头文件名、DHT11初始化函数名
三. 注意事项
(1)PA7-HDQ
结语
不得不说我是怎么一步步改的。
首先就是参照我之前改好的文件,添加了读取函数,发现不行,读取必须要改引脚模式为输入模式。
后来又发现必须要写DHT11_Check,先判断能不能采集,就是到了DHT11发数据的时间没。不过还是不行,一般是时序问题,把之前的时延搬过来,不行。
怀疑读取函数有问题,再搬过来,果然是的。
最后稍微研究了一下读函数的问题,便解决了。文章来源:https://www.toymoban.com/news/detail-488553.html
还是问题定位更加折磨啊!文章来源地址https://www.toymoban.com/news/detail-488553.html
到了这里,关于蓝桥杯嵌入式——扩展板DHT11(更新)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!