/*
|
* 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;
|
}
|