#include "dht11.h" #include "bitband.h" #include "systick.h" #define DATA_OUT PCOut(10) #define DATA_IN PCIn(10) // 将连接 DHT11 的管脚设置为浮空输入(变为输入模式) static void dht11_set_input(void) { GPIO_InitTypeDef GPIO_InitStruct; // 浮空输入模式 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOC, &GPIO_InitStruct); } // 将连接 DHT11 的管脚设置为推挽输出或开漏输出(变为输出模式) static void dht11_set_output(void) { GPIO_InitTypeDef GPIO_InitStruct; // 开漏输出模式 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStruct); } // 将连接 DHT11 的管脚设置位输出状态为 s(0, 1) static void dht11_set_output_status(int s) { dht11_set_output(); DATA_OUT = s ? 1 : 0; } // 将连接 DHT11 的管脚设置位输出状态为 s(0, 1) static int dht11_get_input_status() { dht11_set_input(); return DATA_IN; } // 初始化 DHT11 控制器 void dht11_init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 设置位浮空输入 dht11_set_input(); // 初始化时钟(防止主函数内忘记初始化) systick_init(); } // 获取 DHT11 传感器的 40位 数据,放入buf中 // 成功返回 1. 失败返回 0 int dht11_get_values(u8 buf[5]) { u8 status = 0; u8 time = 0; // 用于记录缓冲区地址 int i; int bit; u8 temp = 0; // 发送起始信号 // 先保证数据线位高电平 dht11_set_output_status(1); // 发送起始信号 dht11_set_output_status(0); delay_ms(20); // 拉高 dht11_set_output_status(1); delay_us(20); // 等待 40us,如果有数据线没被拉低,则说明设备不存在 do { // 获取输入的状态 status = dht11_get_input_status(); delay_us(2); time++; } while (status == 1 && time < 20); if (temp >= 20) { return 0; } // 等待转为高电平 while (!dht11_get_input_status()); // 读取 40bit 数据 // i 表示字节的缩影 for (i = 0; i < 5; i++) { // temp 表示正在读取的一个字节 temp = 0; for (bit = 0; bit < 8; bit++) { // 等待转为低电平 while(dht11_get_input_status()); // 等待转为高电平 while(!dht11_get_input_status()); delay_us(40); // 将 40us 后的电平状态放入 temp 的最低位 temp <<= 1; temp |= dht11_get_input_status(); } // 将获取到的一个字节填入数组中 buf[i] = temp; } // 主机拉高 dht11_set_output_status(1); return 1; }