一、说明
HAL库,DeepSeek写的代码,一遍过。
二、源码
(1)DHT11.c
// dht11.c
#include "dht11.h"
#define DHT11_TIMEOUT 10000
// 微秒级延时函数(72MHz主频校准)
void DHT11_DelayUs(uint16_t us)
{
uint32_t delay = us * (SystemCoreClock / 8000000); // 72MHz: us*9
while(delay--) {
__NOP();
}
}
static void Set_Pin_Output(DHT11_HandleTypeDef* hdht11) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = hdht11->GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(hdht11->GPIOx, &GPIO_InitStruct);
}
static void Set_Pin_Input(DHT11_HandleTypeDef* hdht11) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = hdht11->GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(hdht11->GPIOx, &GPIO_InitStruct);
}
static uint8_t DHT11_CheckResponse(DHT11_HandleTypeDef* hdht11) {
uint32_t timeout = 0;
Set_Pin_Input(hdht11);
// 等待80us低电平
while(HAL_GPIO_ReadPin(hdht11->GPIOx, hdht11->GPIO_Pin) == GPIO_PIN_RESET) {
if(timeout++ > DHT11_TIMEOUT) return DHT11_ERROR_TIMEOUT;
}
timeout = 0;
// 等待80us高电平
while(HAL_GPIO_ReadPin(hdht11->GPIOx, hdht11->GPIO_Pin) == GPIO_PIN_SET) {
if(timeout++ > DHT11_TIMEOUT) return DHT11_ERROR_TIMEOUT;
}
return DHT11_OK;
}
static uint8_t DHT11_ReadByte(DHT11_HandleTypeDef* hdht11) {
uint8_t data = 0;
for(int i=0; i<8; i++) {
uint32_t timeout = 0;
while(HAL_GPIO_ReadPin(hdht11->GPIOx, hdht11->GPIO_Pin) == GPIO_PIN_RESET) {
if(timeout++ > DHT11_TIMEOUT) return 0;
}
DHT11_DelayUs(40); // 精确40us延时
if(HAL_GPIO_ReadPin(hdht11->GPIOx, hdht11->GPIO_Pin) == GPIO_PIN_SET) {
data |= (1 << (7-i));
timeout = 0;
while(HAL_GPIO_ReadPin(hdht11->GPIOx, hdht11->GPIO_Pin) == GPIO_PIN_SET) {
if(timeout++ > DHT11_TIMEOUT) return 0;
}
}
}
return data;
}
void DHT11_Init(DHT11_HandleTypeDef* hdht11, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
hdht11->GPIOx = GPIOx;
hdht11->GPIO_Pin = GPIO_Pin;
hdht11->temperature = 0;
hdht11->humidity = 0;
Set_Pin_Output(hdht11);
HAL_GPIO_WritePin(hdht11->GPIOx, hdht11->GPIO_Pin, GPIO_PIN_SET);
}
uint8_t DHT11_Read(DHT11_HandleTypeDef* hdht11) {
uint8_t data[5] = {0};
// 发送起始信号
Set_Pin_Output(hdht11);
HAL_GPIO_WritePin(hdht11->GPIOx, hdht11->GPIO_Pin, GPIO_PIN_RESET);
HAL_Delay(18); // 18ms低电平
HAL_GPIO_WritePin(hdht11->GPIOx, hdht11->GPIO_Pin, GPIO_PIN_SET);
DHT11_DelayUs(30); // 主机拉高30us
// 检测DHT11响应
if(DHT11_CheckResponse(hdht11) != DHT11_OK) {
return DHT11_ERROR_TIMEOUT;
}
// 读取40位数据
for(int i=0; i<5; i++) {
data[i] = DHT11_ReadByte(hdht11);
if(data[i] == 0) return DHT11_ERROR_TIMEOUT;
}
// 校验和验证
if(data[4] != (data[0] + data[1] + data[2] + data[3])) {
return DHT11_ERROR_CHECKSUM;
}
hdht11->humidity = data[0];
hdht11->temperature = data[2];
return DHT11_OK;
}
(2)DHT11.h
// dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f1xx_hal.h"
#define DHT11_OK 0
#define DHT11_ERROR_CHECKSUM 1
#define DHT11_ERROR_TIMEOUT 2
typedef struct {
GPIO_TypeDef* GPIOx;
uint16_t GPIO_Pin;
uint8_t temperature;
uint8_t humidity;
} DHT11_HandleTypeDef;
void DHT11_Init(DHT11_HandleTypeDef* hdht11, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint8_t DHT11_Read(DHT11_HandleTypeDef* hdht11);
void DHT11_DelayUs(uint16_t us);
#ifdef __cplusplus
}
#endif
#endif /* __DHT11_H */
(3)main.c
#include "main.h"
#include "adc.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "st7735.h"
#include "dht11.h"
char numStr[3][20] ={0};
DHT11_HandleTypeDef hdht11;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
DHT11_Init(&hdht11, GPIOA, GPIO_PIN_3);
ST7735_Init();
while (1)
{
if(DHT11_Read(&hdht11) == DHT11_OK) {
// printf("Temp: %dC, Humi: %d%%rn",
// hdht11.temperature, hdht11.humidity);
}
uint16_t adcValueChannel1 = Read_ADC_Value(1); // 读取通道 1 的 ADC 值
uint16_t adcValueChannel2 = Read_ADC_Value(2); // 读取通道 2 的 ADC 值
sprintf(numStr[0], "%d", hdht11.temperature);
sprintf(numStr[1], "%d", hdht11.humidity);
ST7735_DrawString(0, 40, numStr[0], ST7735_MAGENTA , ST7735_BLACK, &Font_11x18);
ST7735_DrawString(0, 80, numStr[1], ST7735_MAGENTA, ST7735_BLACK, &Font_11x18);
HAL_Delay(2000);
}
/* USER CODE END 3 */
}
三、注意事项
微妙延时函数,根据自己主频和晶振更改参数:
// 微秒级延时函数(72MHz主频校准)
void DHT11_DelayUs(uint16_t us)
{
uint32_t delay = us * (SystemCoreClock / 8000000); // 72MHz: us*9
while(delay--) {
__NOP();
}
}
阅读全文
431