#include "mw_dht11.h" #include "stdint.h" /* user define */ #include "public_diy.h" #include "bsp_timer.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" /* 用户头文件定义 */ #define DHT11BUS_GPIO_PORT (GPIOB) #define DHT11BUS_GPIO_PIN (GPIO_Pin_1) #define DHT11BUS_GPIO_RCC (RCC_APB2Periph_GPIOB) /* 用户安装函数 */ /************************************************************************************* * @brief dht11用 延迟若干us * @param[in/out] delay_us【参数注释】 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_delay_us(uint16_t delay_us) { bsp_DelayUS(delay_us); } /************************************************************************************* * @brief dht11用 延迟若干ms * @param[in/out] delay_ms【参数注释】 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_delay_ms(uint16_t delay_ms) { bsp_DelayMS(delay_ms); } /************************************************************************************* * @brief dht11的单总线为 输出 高电平 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_output_high(void) { // DHT11BUS_GPIO_PORT->BSRR = DHT11BUS_GPIO_PIN; // GPIO_SetBits(DHT11BUS_GPIO_PORT, DHT11BUS_GPIO_PIN); GPIO_WriteBit(DHT11BUS_GPIO_PORT, DHT11BUS_GPIO_PIN, (BitAction)1); } /************************************************************************************* * @brief dht11的单总线为 输出 低电平 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_output_low(void) { // DHT11BUS_GPIO_PORT->BRR = DHT11BUS_GPIO_PIN; GPIO_WriteBit(DHT11BUS_GPIO_PORT, DHT11BUS_GPIO_PIN, (BitAction)0); } /************************************************************************************* * @brief 将dht11的单总线改为输入 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_io_input(void) { // GPIO_InitTypeDef GPIO_InitStructure; /* 打开GPIO时钟 */ // RCC_APB2PeriphClockCmd(DHT11BUS_GPIO_RCC, ENABLE); // GPIO_InitStructure.GPIO_Pin = DHT11BUS_GPIO_PIN; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; /* 设为 输出开漏模式 */ // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* IO口最大速度 */ // GPIO_Init(DHT11BUS_GPIO_PORT, &GPIO_InitStructure); // #if DHT11BUS_GPIO_PIN == GPIO_Pin_0 // DHT11BUS_GPIO_PORT->CRL &= 0xFFFFFFF0; // DHT11BUS_GPIO_PORT->CRL |= 8; // #endif // #if DHT11BUS_GPIO_PIN == GPIO_Pin_1 DHT11BUS_GPIO_PORT->CRL &= 0xFFFFFF0F; DHT11BUS_GPIO_PORT->CRL |= 4 << 4; // #endif // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_2 // DHT11BUS_GPIO_PORT->CRL &= 0xFFFFF0FF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 8; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_3 // DHT11BUS_GPIO_PORT->CRL &= 0xFFFF0FFF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 12; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_4 // DHT11BUS_GPIO_PORT->CRL &= 0xFFF0FFFF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 16; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_5 // DHT11BUS_GPIO_PORT->CRL &= 0xFF0FFFFF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 20; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_6 // DHT11BUS_GPIO_PORT->CRL &= 0xF0FFFFFF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 24; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_7 // DHT11BUS_GPIO_PORT->CRL &= 0x0FFFFFFF; // DHT11BUS_GPIO_PORT->CRL |= 8 << 28; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_8 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFFFF0; // DHT11BUS_GPIO_PORT->CRH |= 8; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_9 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFFF0F; // DHT11BUS_GPIO_PORT->CRH |= 8 << 4; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_10 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFF0FF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 8; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_11 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFF0FFF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 12; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_12 // DHT11BUS_GPIO_PORT->CRH &= 0xFFF0FFFF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 16; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_13 // DHT11BUS_GPIO_PORT->CRH &= 0xFF0FFFFF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 20; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_14 // DHT11BUS_GPIO_PORT->CRH &= 0xF0FFFFFF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 24; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_15 // DHT11BUS_GPIO_PORT->CRH &= 0x0FFFFFFF; // DHT11BUS_GPIO_PORT->CRH |= 8 << 28; // #endif } /************************************************************************************* * @brief 将dht11的单总线改为输出 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ static void dht11_io_output(void) { // #if ((DHT11BUS_GPIO_PIN) == (GPIO_Pin_0)) // DHT11BUS_GPIO_PORT->CRL &= 0xFFFFFFF0; // DHT11BUS_GPIO_PORT->CRL |= 3; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_1 DHT11BUS_GPIO_PORT->CRL &= 0xFFFFFF0F; DHT11BUS_GPIO_PORT->CRL |= 7 << 4; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_2 // DHT11BUS_GPIO_PORT->CRL &= 0xFFFFF0FF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 8; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_3 // DHT11BUS_GPIO_PORT->CRL &= 0xFFFF0FFF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 12; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_4 // DHT11BUS_GPIO_PORT->CRL &= 0xFFF0FFFF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 16; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_5 // DHT11BUS_GPIO_PORT->CRL &= 0xFF0FFFFF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 20; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_6 // DHT11BUS_GPIO_PORT->CRL &= 0xF0FFFFFF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 24; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_7 // DHT11BUS_GPIO_PORT->CRL &= 0x0FFFFFFF; // DHT11BUS_GPIO_PORT->CRL |= 3 << 28; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_8 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFFFF0; // DHT11BUS_GPIO_PORT->CRH |= 3; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_9 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFFF0F; // DHT11BUS_GPIO_PORT->CRH |= 3 << 4; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_10 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFFF0FF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 8; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_11 // DHT11BUS_GPIO_PORT->CRH &= 0xFFFF0FFF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 12; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_12 // DHT11BUS_GPIO_PORT->CRH &= 0xFFF0FFFF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 16; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_13 // DHT11BUS_GPIO_PORT->CRH &= 0xFF0FFFFF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 20; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_14 // DHT11BUS_GPIO_PORT->CRH &= 0xF0FFFFFF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 24; // #elif DHT11BUS_GPIO_PIN == GPIO_Pin_15 // DHT11BUS_GPIO_PORT->CRH &= 0x0FFFFFFF; // DHT11BUS_GPIO_PORT->CRH |= 3 << 28; // #endif } /************************************************************************************* * @brief 获取dht11输出状态 * @return uint8_t 【返回值注释】 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ uint8_t dht11_read_io_state(void) { // return (uint8_t)(DHT11BUS_GPIO_PORT->ODR & DHT11BUS_GPIO_PIN); return GPIO_ReadInputDataBit(DHT11BUS_GPIO_PORT, DHT11BUS_GPIO_PIN); } /************************************************************************************* * @brief dht11 单总线所需的gpio初始化 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ void dht11_gpio_init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 打开GPIO时钟 */ RCC_APB2PeriphClockCmd(DHT11BUS_GPIO_RCC, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11BUS_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 设为 输出开漏模式 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* IO口最大速度 */ GPIO_Init(DHT11BUS_GPIO_PORT, &GPIO_InitStructure); dht11_output_high(); } /************************************************************************************* * @brief dht11开始信号 * @return uint8_t RET_ERROR RET_OK * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ uint8_t dht11_start(void) { uint8_t tmp_timer = 0; // 关总中断 DISABLE_INT(); //1.配置引脚为输出模式 dht11_io_output(); //2.把引脚电平拉低并持续20ms dht11_output_low(); dht11_delay_ms(20); //3.把引脚电平拉高并持续20us dht11_output_high(); dht11_delay_us(30); dht11_io_input(); // 等待dht11 拉低 while(dht11_read_io_state() == 0 && tmp_timer < 101) { tmp_timer++; dht11_delay_us(1); __NOP(); } if(tmp_timer > 100 || tmp_timer < 20) { return RET_ERROR; } // 检测是否存在第二个高电平 tmp_timer = 0; // 重置计数器 while (dht11_read_io_state() == 1 && tmp_timer < 101) // 等待DHT11释放总线,持续时间40~80us { tmp_timer++; // 总线拉高时计数 dht11_delay_us(1); } ENABLE_INT(); // 开总中断 if (tmp_timer>100 || tmp_timer<20) // 检测响应信号之后的高电平 { return RET_ERROR; } // 均存在, 响应正常 return RET_OK; } uint8_t dht11_read_byte(uint8_t *ret_byte) { uint8_t tmp_timer = 0; uint8_t tmp_i; // uint8_t ret_byte = 0; DISABLE_INT(); // 关总中断 dht11_io_input(); for (tmp_i = 0; tmp_i < 8; tmp_i++) { /* 等待低电平,数据位前都有50us低电平时隙 */ while (dht11_read_io_state() > 0 && tmp_timer < 101) { tmp_timer++; dht11_delay_us(1); } if(tmp_timer > 100) { return RET_ERROR; } tmp_timer = 0; /* 等待高电平,开始传输数据位 */ while (dht11_read_io_state() == 0 && tmp_timer < 101) { tmp_timer++; dht11_delay_us(1); } if(tmp_timer > 100) { return RET_ERROR; } dht11_delay_us(40); *ret_byte <<= 1; // 因高位在前,所以左移byt,最低位补0 if (dht11_read_io_state() > 0) // 将总线电平值读取到byt最低位中 { *ret_byte |= 0x01; } } ENABLE_INT(); // 开总中断 return RET_OK; } /** * @brief 读取数据 * @param Temp_H 温度整数部分 * @param Temp_L 温度小数部分 * @param Humi_H 湿度整数部分 * @param Humi_L 湿度小数部分 * @retval 0-成功,1-失败 */ uint8_t mw_dht11_read_data(uint8_t *Temp_H,uint8_t *Temp_L,uint8_t *Humi_H,uint8_t *Humi_L) { uint8_t sta = RET_ERROR; uint8_t i; uint8_t buf[5]; if(dht11_start() == RET_OK) // 检测响应信号 { for(i=0;i<5;i++) // 读取40位数据 { sta = dht11_read_byte(&buf[i]); // 读取1字节数据 if(sta == RET_ERROR) { return RET_ERROR; } } if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) // 校验成功 { *Humi_H = buf[0]; // 湿度 整数部分数据 *Humi_L = buf[1]; // 湿度 小数部分数据 *Temp_H = buf[2]; // 温度 整数部分数据 *Temp_L = buf[3]; // 温度 小数部分数据 return RET_OK; } else { return RET_ERROR; } } else // 响应失败返回-1 { *Temp_H = 0; *Temp_L = 0; *Humi_H = 0; *Humi_L = 0; return RET_ERROR; } } /************************************************************************************* * @brief dht11初始化 * * @warning 【不可重入,阻塞等警告】 * @note 【重大修改】 *************************************************************************************/ void mw_dht11_init(void) { dht11_gpio_init(); }