阅读原理图,温湿度模块通过D2连线接到STM32 PB8引脚上。
阅读温湿度传感器说明书,主从机基于微秒级完成通信,要实现微秒级通信需要使用一个定时器。故而启用TIM6。
获取到以上两点信息后,使用CubeMX生成代码。
配置PB8为GPIO_Input ;配置PA9,PA10 为 UART_TX与UART_RX。
在PB8中加上用户标签DHT。
定时器启用,并设置预分频系数,向上计数,最大计数周期。
UART串口设置波特率。
完成后生成代码。
dht.c 任务处理文件。
#include "gpio.h"
#include <stdio.h>
void delay_us(uint16_t wait)
{
//TIM6的一个时钟周期是1us
//设置TIM6的计数器的值为1
TIM6->CNT = 0;
//LL_TIM_SetCounter(TIM6, 0);
//LL_TIM_GetCounter(TIM6);
//计数1次是1us,计数wait次就是waitus
while(TIM6->CNT < wait);
}
//等待高、低电平结束
//level:高/低电平
//timeout:超时时间(us)
//返回值:等待的时间(us)
uint32_t wait_level(GPIO_PinState level, uint32_t timeout)
{
uint32_t wait = 0;
while (HAL_GPIO_ReadPin(DHT_GPIO_Port, DHT_Pin) == level)
{
delay_us(1);
wait++;
if (wait >= timeout)
{
break; //超时退出
}
}
return wait;
}
//读取温湿度
void dht_read(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
//将数据引脚设置为输出模式
GPIO_InitStruct.Pin = DHT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DHT_GPIO_Port, &GPIO_InitStruct);
//发送起始信号(输出低电平并持续18ms以上)
HAL_GPIO_WritePin(DHT_GPIO_Port, DHT_Pin, GPIO_PIN_RESET);
HAL_Delay(19);
//将数据引脚设置为输入模式,电平由外部上拉电阻拉高
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(DHT_GPIO_Port, &GPIO_InitStruct);
//主机发送开始信号结束后,延时等待20-40us后,读取DHT1X的响应信号
delay_us(40);
//判断DHT传感器是否发出响应信号(低电平)
if (HAL_GPIO_ReadPin(DHT_GPIO_Port, DHT_Pin) == GPIO_PIN_SET)
{
//如果传感器没有响应,打印错误信息并终止读取
printf("DHT sensor no response\r\n");
return;
}
//如果传感器响应,等待响应信号结束
//等待低电平结束
wait_level(GPIO_PIN_RESET, 80);
//等待高电平结束
wait_level(GPIO_PIN_SET, 100);
//保存收到的40bit数据
uint8_t data[5];
uint8_t j;
for (j = 0; j < 5; j++)
{
//读取一个字节
uint8_t i;
for (i = 0; i < 8; i++)
{
//开始接收数据
//统计低电平持续时间
uint32_t low_time = wait_level(GPIO_PIN_RESET, 70);
//统计高电平持续时间
uint32_t high_time = wait_level(GPIO_PIN_SET, 100);
if (low_time > high_time)
{
//收到bit0
data[j] &= (~(0x80 >> i)); //将第i个有效位清0
}
else
{
//收到bit1
data[j] |= (0x80 >> i); //将第i个有效位置1
}
}
}
//当最后一bit数据传送完毕后,DHT1X拉低总线50us
wait_level(GPIO_PIN_RESET, 50);
//计算校验和
//数据传送正确时校验和数据等于
//“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”
//所得结果的末8位。
uint8_t chksum = data[0] + data[1] + data[2] + data[3];
if (chksum != data[4])
{
//校验和错误打印出错信息
printf("checksum error\r\n");
return;
}
//打印温湿度信息
printf("Humidity: %d.%d, ", data[0], data[1]);
printf("Temprature: %d.%d\r\n", data[2], data[3]);
}
主函数里调用一下dht.c里面写好的函数即可,延迟一下降低读的频率,避免刷新的太快。
连上板子运行即可。