382 lines
12 KiB
C
Raw Permalink Normal View History

2026-05-10 21:35:40 +08:00
#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();
}