阿波罗学习--day2(单总线通信DHT11) 📅 2026/7/15 3:25:50 一、通信时序二、原理图三、引脚配置GPIO工作模式--开漏输出四、遇到问题通信失败--没有任何数据传出DHT11.c#include DHT11.h #include delay.h #include gpio.h #include stdio.h /** * brief 复位 DHT11 * param data: 要写入的数据 * retval 无 */ static void dht11_rest(void) { DHT11_DQ_OUT(0); delay_ms(20); DHT11_DQ_OUT(1); delay_us(30); } /** * brief 等待 DHT11 的回应 * param 无 * retval 0, DHT11 正常 * 1, DHT11 异常/不存在 */ uint8_t dht11_check(void) { uint8_t retry 0; uint8_t rval 0; while( DHT11_DQ_IN retry 100 ) { retry; delay_us(1); } if(retry 100) { rval 1; } else { retry 0; while( ! DHT11_DQ_IN retry 100 ) { retry; delay_us(1); } if (retry 100) { rval 1; // 第一段脉冲超时标记故障 } } return rval; } uint8_t dht11_read_bit(void) { uint8_t retry 0; while( DHT11_DQ_IN retry 100 ) //等待上一位的高电平结束 { retry; delay_us(1); } retry 0; while( ! DHT11_DQ_IN retry 100 ) //等待低电平结束 { retry; delay_us(1); } delay_us(40); if(DHT11_DQ_IN) //判断数据位,根据手册判断 { return 1; } else { return 0; } } static uint8_t dht11_read_byte(void) { uint8_t i , data0; for(i0;i8;i) { data 1; //高位数据先行先左移一位 data | dht11_read_bit(); } return data; } /** * brief 从 DHT11 读取一次数据 * param temp: 温度值(范围:-20~60°) * param humi: 湿度值(范围:5%~95%) * retval 0, 正常. * 1, 失败 */ uint8_t dht11_read_data(uint8_t *temp, uint8_t *humi) { uint8_t buf[5]; uint8_t i; dht11_rest(); if( dht11_check() 0) { for(i0;i5;i) { buf[i] dht11_read_byte(); } if(buf[0]buf[1]buf[2]buf[3] buf[4]) { *humi buf[0]; // buf[0] 湿度整数 *temp buf[2]; // buf[2] 温度整数 } } else { return 1; //通信失败 } return 0; } uint8_t dht11_init(void) { GPIO_InitTypeDef gpio_init_struct; __HAL_RCC_GPIOB_CLK_ENABLE(); gpio_init_struct.Pin GPIO_PIN_12; gpio_init_struct.Mode GPIO_MODE_OUTPUT_OD; // 开漏输出 gpio_init_struct.Pull GPIO_PULLUP; // 开启内部上拉关键 gpio_init_struct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, gpio_init_struct); dht11_rest(); return dht11_check(); }.c代码亮点,uint8_t dht11_read_bit(void)中第一个while循环如果上一个bit电平是高电平那么就等待他结束后在读取第二个bit的低电平DHT11.h#ifndef __DHT11_H #define __DHT11_H #include sys.h //#include stm32h7xx_hal.h #include gpio.h /******************************************************************************************/ /* 引脚 定义 */ #define DHT11_GPIO_PORT GPIOB #define DHT11_GPIO_PIN GPIO_PIN_12 /* DHT11端口定义 */ #define DHT11_DQ_OUT(x) do{ x ? \ HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN , GPIO_PIN_SET) : \ HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN , GPIO_PIN_RESET); \ }while(0) /* LED0 RED */ /* 数据端口输入 */ #define DHT11_DQ_IN HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN) /******************************************************************************************/ static void dht11_rest(void); uint8_t dht11_check(void); uint8_t dht11_read_bit(void); static uint8_t dht11_read_byte(void); uint8_t dht11_read_data(uint8_t *temp, uint8_t *humi); uint8_t dht11_init(void); #endif在main函数里面添加这个函数delay_init(480)否则会遇到一下现象看似通信成功实验结果