/* * dht11.c * * Created on: Aug 8, 2021 * Author: Think */ #include "tim.h" #include "gpio.h" #include "main.h" typedef struct w1_gpio_s { GPIO_TypeDef *group; uint16_t pin; } w1_gpio_t; static w1_gpio_t W1Dat = /* IO pin connected to PA5 */ { .group = GPIOA, .pin = GPIO_PIN_5, }; #define W1DQ_Input() \ { \ GPIO_InitTypeDef GPIO_InitStruct = {0}; \ GPIO_InitStruct.Pin = W1Dat.pin; \ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \ GPIO_InitStruct.Pull = GPIO_PULLUP; \ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \ HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \ } #define W1DQ_Output() \ { \ GPIO_InitTypeDef GPIO_InitStruct = {0}; \ GPIO_InitStruct.Pin = W1Dat.pin; \ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \ GPIO_InitStruct.Pull = GPIO_NOPULL; \ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \ HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \ } #define W1DQ_Write(x) HAL_GPIO_WritePin(W1Dat.group, W1Dat.pin, \ (x==1)?GPIO_PIN_SET:GPIO_PIN_RESET) #define W1DQ_Read() HAL_GPIO_ReadPin(W1Dat.group, W1Dat.pin) /* 主机发送起始信号 */ static void DHT11_StartSignal(void) { W1DQ_Output(); /* 主机拉低 >= 18ms */ W1DQ_Write(0); HAL_Delay(20); /* 主机拉高 >= 20~40us */ W1DQ_Write(1); delay_us(30); W1DQ_Input(); } uint8_t DHT11_RespondSignal(void) { uint8_t retry = 0; /* 总线变为低电平说明从设备发送了响应信号: 80us */ while( W1DQ_Read() && retry <100) { retry++; delay_us(1); } /* 超时没有收到响应信号 */ if(retry >= 100) return 1; /* 从设备再把总线拉高表示从设备要发送数据了: 80us */ retry = 0; while( !W1DQ_Read() && retry <100) { retry++; delay_us(1); } /* 超时没有收到数据开始信号 */ if(retry >= 100) return 1; return 0; } uint8_t DHT11_ReadBit(void) //读取一个位 { uint8_t retry = 0; /* 从设备回复的每个位数据以低电平标置开始: 50us */ while( W1DQ_Read() && retry<100 ) { retry++; delay_us(1); } /* 数据位都用高电平表示, 但高电平的长短决定了数据是 1 or 0 */ retry = 0; while( !W1DQ_Read() && retry<100 ) { retry++; delay_us(1); } /* 判断数据位是 1(70us) or 0(26~28us)*/ delay_us(40); if( W1DQ_Read() ) return 1; else return 0; } uint8_t DHT11_ReadByte(void) //读取一个字节返回值位采集值 { uint8_t i,dat; dat = 0; for(i=0; i<8; i++) { dat <<= 1; dat |= DHT11_ReadBit(); //每读取到一个位放到最后一位 } return dat; } int DHT11_SampleData(float *temperature, float *humidity) { uint8_t humi_H8bit; uint8_t humi_L8bit; uint8_t temp_H8bit; uint8_t temp_L8bit; uint8_t check_sum; if( !temperature || !humidity ) return -1; /* 主机发起起始信号并等到从设备的响应信号 */ DHT11_StartSignal(); if( 0 != DHT11_RespondSignal() ) return -2; humi_H8bit = DHT11_ReadByte(); humi_L8bit = DHT11_ReadByte(); temp_H8bit = DHT11_ReadByte(); temp_L8bit = DHT11_ReadByte(); check_sum = DHT11_ReadByte(); if( (humi_H8bit+humi_L8bit+temp_H8bit+temp_L8bit) != check_sum ) return -3; *humidity = (humi_H8bit*100 + humi_L8bit) / 100.00; *temperature = (temp_H8bit*100 + temp_L8bit) / 100.00; return 0; }