2026-05-10 21:35:40 +08:00

382 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}