DHT11驱动
介绍
参考《HAL快速入门与项目实战(基于DshanMCU-F407)_V1.0》
参考《dht11_datasheet.pdf》
DHT11 驱动涉及引脚的读取操作,具体操作在驱动程序注释中已经说明
驱动程序
driver_dht11.h
#ifndef __DRIVER_DHT11_H__
#define __DRIVER_DHT11_H__
#include "main.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* @brief dht11 handle structure definition
*/
typedef struct dht11_handle_s
{
uint8_t (*bus_init)(void); /**< point to a bus_init function address */
uint8_t (*bus_read)(uint8_t *value); /**< point to a bus_read function address */
uint8_t (*bus_write)(uint8_t value); /**< point to a bus_write function address */
uint8_t (*bus_deinit)(void); /**< point to a bus_deinit function address */
void (*delay_ms)(uint32_t ms); /**< point to a delay_ms function address */
void (*delay_us)(uint32_t us); /**< point to a delay_us function address */
void (*enable_irq)(void); /**< point to an enable_irq function address */
void (*disable_irq)(void); /**< point to a disable_irq function address */
void (*debug_print)(const char *const fmt, ...); /**< point to a debug_print function address */
uint8_t inited; /**< inited flag */
} dht11_handle_t;
/**
* @brief dht11 info structure definition
*/
typedef struct dht11_info_s
{
char chip_name[32]; /**< chip name */
char manufacturer_name[32]; /**< manufacturer name */
char interface[8]; /**< chip interface name */
float supply_voltage_min_v; /**< chip min supply voltage */
float supply_voltage_max_v; /**< chip max supply voltage */
float max_current_ma; /**< chip max current */
float temperature_min; /**< chip min operating temperature */
float temperature_max; /**< chip max operating temperature */
uint32_t driver_version; /**< driver version */
} dht11_info_t;
/**
* @brief initialize dht11_handle_t structure
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] STRUCTURE is dht11_handle_t
* @note none
*/
#define DRIVER_DHT11_LINK_INIT(HANDLE, STRUCTURE) memset(HANDLE, 0, sizeof(STRUCTURE))
/**
* @brief link bus_init function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a bus_init function address
* @note none
*/
#define DRIVER_DHT11_LINK_BUS_INIT(HANDLE, FUC) (HANDLE)->bus_init = FUC
/**
* @brief link bus_deinit function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a bus_deinit function address
* @note none
*/
#define DRIVER_DHT11_LINK_BUS_DEINIT(HANDLE, FUC) (HANDLE)->bus_deinit = FUC
/**
* @brief link bus_read function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a bus_read function address
* @note none
*/
#define DRIVER_DHT11_LINK_BUS_READ(HANDLE, FUC) (HANDLE)->bus_read = FUC
/**
* @brief link bus_write function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a bus_write function address
* @note none
*/
#define DRIVER_DHT11_LINK_BUS_WRITE(HANDLE, FUC) (HANDLE)->bus_write = FUC
/**
* @brief link delay_ms function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a delay_ms function address
* @note none
*/
#define DRIVER_DHT11_LINK_DELAY_MS(HANDLE, FUC) (HANDLE)->delay_ms = FUC
/**
* @brief link delay_us function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a delay_us function address
* @note none
*/
#define DRIVER_DHT11_LINK_DELAY_US(HANDLE, FUC) (HANDLE)->delay_us = FUC
/**
* @brief link enable_irq function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to an enable_irq function address
* @note none
*/
#define DRIVER_DHT11_LINK_ENABLE_IRQ(HANDLE, FUC) (HANDLE)->enable_irq = FUC
/**
* @brief link disable_irq function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a disable_irq function address
* @note none
*/
#define DRIVER_DHT11_LINK_DISABLE_IRQ(HANDLE, FUC) (HANDLE)->disable_irq = FUC
/**
* @brief link debug_print function
* @param[in] HANDLE points to a dht11 handle structure
* @param[in] FUC points to a debug_print function address
* @note none
*/
#define DRIVER_DHT11_LINK_DEBUG_PRINT(HANDLE, FUC) (HANDLE)->debug_print = FUC
/**
* @brief get chip's information
* @param[out] *info points to a dht11 info structure
* @return status code
* - 0 success
* - 2 handle is NULL
* @note none
*/
uint8_t dht11_info(dht11_info_t *info);
/**
* @brief initialize the chip
* @param[in] *handle points to a dht11 handle structure
* @return status code
* - 0 success
* - 1 bus initialization failed
* - 2 handle is NULL
* - 3 linked functions is NULL
* - 4 reset failed
* @note none
*/
uint8_t dht11_init(dht11_handle_t *handle);
/**
* @brief close the chip
* @param[in] *handle points to a dht11 handle structure
* @return status code
* - 0 success
* - 1 bus deinit failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_deinit(dht11_handle_t *handle);
/**
* @brief read the temperature and humidity data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *temperature_raw points to a raw temperature buffer
* @param[out] *temperature_s points to a converted temperature buffer
* @param[out] *humidity_raw points to a raw humidity buffer
* @param[out] *humidity_s points to a converted humidity buffer
* @return status code
* - 0 success
* - 1 read temperature humidity failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_temperature_humidity(dht11_handle_t *handle, uint16_t *temperature_raw, float *temperature_s,
uint16_t *humidity_raw, uint8_t *humidity_s);
/**
* @brief read the humidity data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *raw points to a raw humidity buffer
* @param[out] *s points to a converted humidity buffer
* @return status code
* - 0 success
* - 1 read humidity failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_humidity(dht11_handle_t *handle, uint16_t *raw, uint8_t *s);
/**
* @brief read the temperature data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *raw points to a raw temperature buffer
* @param[out] *s points to a converted temperature buffer
* @return status code
* - 0 success
* - 1 read temperature failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_temperature(dht11_handle_t *handle, uint16_t *raw, float *s);
#ifdef __cplusplus
}
#endif
#endif
driver_dht11.c
#include "driver_dht11.h"
/**
* @brief chip information definition
*/
#define CHIP_NAME "ASAIR DHT11" /**< chip name */
#define MANUFACTURER_NAME "ASAIR" /**< manufacturer name */
#define SUPPLY_VOLTAGE_MIN 3.3f /**< chip min supply voltage */
#define SUPPLY_VOLTAGE_MAX 5.5f /**< chip max supply voltage */
#define MAX_CURRENT 1.0f /**< chip max current */
#define TEMPERATURE_MIN -20.0f /**< chip min operating temperature */
#define TEMPERATURE_MAX 60.0f /**< chip max operating temperature */
#define DRIVER_VERSION 2000 /**< driver version */
/**
* @brief reset the chip
* @param[in] *handle points to a dht11 handle structure
* @return status code
* - 0 success
* - 1 no response
* @note none
*
* 重置 DHT11,初始化通信
*/
static uint8_t a_dht11_reset(dht11_handle_t *handle)
{
uint8_t retry = 0;
uint8_t res;
uint8_t value;
/* 将单通信总线拉低,MCU的I/O设置为输出,同时输出低电平 */
res = handle->bus_write(0); /* set low */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus write 0 failed.\n"); /* write failed */
return 1; /* return error */
}
/* 低电平保持时间不能小于18ms(最大不得超过30ms)*/
handle->delay_ms(20); /* wait 20ms */
/* 这里给 DHT11 发送起始信号时,为了严格遵守时序要求可以禁用全局中断,但并不是必要操作 */
handle->disable_irq(); /* disable interrupt */
/* 主机拉低后释放总线,输出1,外部上拉电阻拉高总线,等待 DHT11 拉低作为应答 */
res = handle->bus_write(1); /* set high */
if (res != 0) /* check result */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus write 1 failed.\n"); /* write failed */
return 1; /* return error */
}
/* DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束(即主控拉低引脚后拉高引脚)*/
/* 延迟一段时间后 DHT11的DATA引脚处于输出状态 */
handle->delay_us(30); /* wait 20-40us */
/* DHT11 会输出83微秒的低电平作为应答信号,此时MCU读取引脚电平状态,判断 DHT11 是否给出响应 */
res = handle->bus_read((uint8_t *)&value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
/* 循环等待 83us 内的应答信号,这里略微增加了延迟时间到100us */
while ((value != 0) && (retry < 100)) /* wait 40-80us */
{
res = handle->bus_read((uint8_t *)&value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
retry++; /* retry times++ */
handle->delay_us(1); /* delay 1us */
}
/* 超时,表明传感器未给出响应,没有正常工作 */
if (retry >= 100) /* if retry times is over 100 times */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus no response.\n"); /* no response */
return 1; /* return error */
}
else
{
retry = 0; /* reset retry times */
}
/* 走到这里说明 DHT11 已经给出响应信号,紧接着输出87微秒的高电平通知MCU准备接收数据 */
res = handle->bus_read((uint8_t *)&value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
/* 循环等待 87us 内的高电平通知信号,这里略微增加了延迟时间到100us */
while ((!value) && (retry < 100)) /* wait for 40-80us */
{
res = handle->bus_read((uint8_t *)&value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
retry++; /* retry times++ */
handle->delay_us(1); /* delay 1 us */
}
/* 超时,表明传感器未能正常工作拉高总线给出数据 */
if (retry >= 100) /* if retry times is over 100 times */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: bus no response.\n"); /* no response */
return 1; /* return error */
}
/* 恢复全局中断 */
handle->enable_irq(); /* enable interrupt */
return 0; /* success return 0 */
}
/**
* @brief read one bit
* @param[in] *handle points to a dht11 handle structure
* @param[out] *value points to a value buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
static uint8_t a_dht11_read_bit(dht11_handle_t *handle, uint8_t *value)
{
uint8_t retry = 0;
uint8_t res;
/* DHT11 会输出83微秒的低电平作为应答信号,此时MCU读取引脚电平状态,判断 DHT11 是否给出响应 */
res = handle->bus_read((uint8_t *)value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
/* 循环等待 83us 内的应答信号,这里略微增加了延迟时间到100us */
while (((*value) != 0) && (retry < 100)) /* wait 100us */
{
res = handle->bus_read((uint8_t *)value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
retry++; /* retry times++ */
handle->delay_us(1); /* delay 1 us */
}
retry = 0; /* reset retry times */
/* 走到这里说明 DHT11 已经给出响应信号,紧接着输出87微秒的高电平通知MCU准备接收数据 */
res = handle->bus_read((uint8_t *)value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
/* 循环等待 87us 内的高电平通知信号,这里略微增加了延迟时间到100us */
while ((!(*value)) && (retry < 100)) /* wait 100us */
{
res = handle->bus_read((uint8_t *)value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
retry++; /* retry times++ */
handle->delay_us(1); /* wait 1 us */
}
/* 87us 的数据通知信号发送后
逻辑 "1" 和 逻辑 "0" 发送前会有 54us 的低电平时刻
这里延时 40us 用来同步 DHT11 稳定后的高电平数据,根据高电平的时长来判断是 "1" 还是 "0"
高电平的时间窗口是 23us-27us 在 40us 以内为 "0",高电平的时间窗口是 68us-74us 在 40us 以外为 "1"
*/
handle->delay_us(40); /* wait 40us */
/* 读取此时总线上的电平信号 */
res = handle->bus_read((uint8_t *)value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
else
{
return 0; /* success return 0 */
}
}
/**
* @brief read one byte
* @param[in] *handle points to a dht11 handle structure
* @param[out] *byte points to a byte buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
static uint8_t a_dht11_read_byte(dht11_handle_t *handle, uint8_t *byte)
{
uint8_t i;
uint8_t res;
uint8_t value;
*byte = 0; /* set byte 0 */
for (i = 0; i < 8; i++) /* read 8 bits */
{
/* DHT11 发送时高位先出 */
*byte <<= 1; /* left shift 1 bit */
res = a_dht11_read_bit(handle, (uint8_t *)&value); /* read 1 bit */
if (res != 0) /* check result */
{
handle->debug_print("dht11: bus read failed.\n"); /* read failed */
return 1; /* return error */
}
*byte |= value; /* set LSB */
}
return 0; /* success return 0 */
}
/**
* @brief read the humidity data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *raw points to a raw humidity buffer
* @param[out] *s points to a converted humidity buffer
* @return status code
* - 0 success
* - 1 read humidity failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_humidity(dht11_handle_t *handle, uint16_t *raw, uint8_t *s)
{
/* 一次传送40位数据 */
/* 数据格式: 8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据 + 8bit校验位。 */
uint8_t buf[5];
uint8_t i;
if (handle == NULL) /* check handle */
{
return 2; /* return error */
}
if (handle->inited != 1) /* check handle initialization */
{
return 3; /* return error */
}
if (a_dht11_reset(handle) == 0) /* reset the chip */
{
handle->disable_irq(); /* disable interrupt */
for (i = 0; i < 5; i++) /* read 5 bytes */
{
/* 分别读取 5 个字节的数据 */
if (a_dht11_read_byte(handle, (uint8_t *)&buf[i]) != 0) /* read each byte */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: read byte failed.\n"); /* read failed */
return 1; /* return error */
}
}
handle->enable_irq(); /* enable interrupt */
/* 检查校验位 */
/* 校验位=湿度高位+湿度低位+温度高位+温度低位 */
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) /* calculate checksum */
{
/* 拿到湿度的原始数据 */
*raw = (uint16_t)buf[0] << 8 | buf[1]; /* get raw data */
/* 注:其中湿度小数部分为0。这里只拿湿度数据的整数部分即可 */
*s = buf[0]; /* convert raw data to real data */
return 0; /* success return 0 */
}
else
{
handle->debug_print("dht11: data check failed.\n"); /* checksum error */
return 1; /* return error */
}
}
else
{
handle->debug_print("dht11: reset failed.\n"); /* reset failed */
return 1; /* return error */
}
}
/**
* @brief read the temperature and humidity data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *temperature_raw points to a raw temperature buffer
* @param[out] *temperature_s points to a converted temperature buffer
* @param[out] *humidity_raw points to a raw humidity buffer
* @param[out] *humidity_s points to a converted humidity buffer
* @return status code
* - 0 success
* - 1 read temperature humidity failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_temperature_humidity(dht11_handle_t *handle, uint16_t *temperature_raw, float *temperature_s,
uint16_t *humidity_raw, uint8_t *humidity_s)
{
uint8_t buf[5];
uint8_t i;
if (handle == NULL) /* check handle */
{
return 2; /* return error */
}
if (handle->inited != 1) /* check handle initialization */
{
return 3; /* return error */
}
if (a_dht11_reset(handle) == 0) /* reset the chip */
{
handle->disable_irq(); /* disable interrupt */
/* 读取 5 个字节的数据 */
for (i = 0; i < 5; i++) /* read 5 bytes */
{
if (a_dht11_read_byte(handle, (uint8_t *)&buf[i]) != 0) /* read each byte */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: read byte failed.\n"); /* read failed */
return 1; /* return error */
}
}
handle->enable_irq(); /* enable interrupt */
/* 检验数据 */
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) /* calculate checksum */
{
/* 处理温湿度数据,处理方式与单独的功能里一致,已做详细的注释 */
if (buf[3] > 127) /* if temperature is below zero */
{
*temperature_raw = (uint16_t)buf[2] << 8 | buf[3]; /* get temperature raw data */
*temperature_s= (float)(-(buf[2] * 10 +
(buf[3] & ~(1<<7)))) / 10.0f; /* convert temperature raw data to temperature real data */
}
else
{
*temperature_raw = (uint16_t)buf[2] << 8 | buf[3]; /* get temperature raw data */
*temperature_s= (float)(buf[2]*10 + buf[3]) / 10.0f; /* convert temperature raw data to temperature real data */
}
*humidity_raw = (uint16_t)buf[0] << 8 | buf[1]; /* get humidity raw */
*humidity_s = buf[0]; /* convert humidity raw data to real data */
return 0; /* success return 0 */
}
else
{
handle->debug_print("dht11: data check failed.\n"); /* checksum error */
return 1; /* return error */
}
}
else
{
handle->debug_print("dht11: reset failed.\n"); /* reset failed */
return 1; /* return error */
}
}
/**
* @brief read the temperature data
* @param[in] *handle points to a dht11 handle structure
* @param[out] *raw points to a raw temperature buffer
* @param[out] *s points to a converted temperature buffer
* @return status code
* - 0 success
* - 1 read temperature failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_read_temperature(dht11_handle_t *handle, uint16_t *raw, float *s)
{
uint8_t buf[5];
uint8_t i;
if (handle == NULL) /* check handle */
{
return 2; /* return error */
}
if (handle->inited != 1) /* check handle initialization */
{
return 3; /* return error */
}
if (a_dht11_reset(handle) == 0) /* reset the chip */
{
handle->disable_irq(); /* disable interrupt */
for (i = 0; i < 5; i++) /* read 5 bytes */
{
if (a_dht11_read_byte(handle, (uint8_t *)&buf[i]) != 0) /* read each byte */
{
handle->enable_irq(); /* enable interrupt */
handle->debug_print("dht11: read byte failed.\n"); /* read failed */
return 1; /* return error */
}
}
handle->enable_irq(); /* enable interrupt */
/* 如上操作同读取湿度数据一致,不在说明 */
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) /* calculate checksum */
{
/* 当温度低于0℃时温度数据的低8位的最高位置为1。如果温度低于 0℃ 温度数据的低8位的最高位作为假设的符号位 */
if (buf[3] > 127) /* if temperature is below zero */
{
*raw = (uint16_t)buf[2] << 8 | buf[3]; /* get temperature raw data */
/* 整数部分乘于10加上小数部分只要低7位的数据 */
*s= (float)(-(buf[2] * 10 + (buf[3] & ~(1<<7)))) / 10.0f; /* convert temperature raw data to temperature real data */
}
else
{
*raw = (uint16_t)buf[2] << 8 | buf[3]; /* get temperature raw data */
*s= (float)(buf[2] * 10 + buf[3]) / 10.0f; /* convert temperature raw data to temperature real data */
}
return 0; /* success return 0 */
}
else
{
handle->debug_print("dht11: data check failed.\n"); /* checksum error */
return 1; /* return error */
}
}
else
{
handle->debug_print("dht11: reset failed.\n"); /* reset failed */
return 1; /* return error */
}
}
/**
* @brief initialize the chip
* @param[in] *handle points to a dht11 handle structure
* @return status code
* - 0 success
* - 1 bus initialization failed
* - 2 handle is NULL
* - 3 linked functions is NULL
* - 4 reset failed
* @note none
*/
uint8_t dht11_init(dht11_handle_t *handle)
{
if (handle == NULL) /* check handle */
{
return 2; /* return error */
}
if (handle->debug_print == NULL) /* check debug_print */
{
return 3; /* return error */
}
if (handle->bus_init == NULL) /* check bus_init */
{
handle->debug_print("dht11: bus_init is null.\n"); /* bus_init is null */
return 3; /* return error */
}
if (handle->bus_deinit == NULL) /* check bus_deinit */
{
handle->debug_print("dht11: bus_deinit is null.\n"); /* bus_deinit is null */
return 3; /* return error */
}
if (handle->bus_read == NULL) /* check bus_read */
{
handle->debug_print("dht11: bus_read is null.\n"); /* bus_read is null */
return 3; /* return error */
}
if (handle->bus_write == NULL) /* check bus_write */
{
handle->debug_print("dht11: bus_write is null.\n"); /* bus_write is null */
return 3; /* return error */
}
if (handle->delay_ms == NULL) /* check delay_ms */
{
handle->debug_print("dht11: delay_ms is null.\n"); /* delay_ms is null */
return 3; /* return error */
}
if (handle->delay_us == NULL) /* check delay_us */
{
handle->debug_print("dht11: delay_us is null.\n"); /* delay_us is null */
return 3; /* return error */
}
if (handle->enable_irq == NULL) /* check enable_irq */
{
handle->debug_print("dht11: enable_irq is null.\n"); /* enable_irq is null */
return 3; /* return error */
}
if (handle->disable_irq == NULL) /* check disable_irq */
{
handle->debug_print("dht11: disable_irq is null.\n"); /* disable_irq is null */
return 3; /* return error */
}
if (handle->bus_init() != 0) /* initialize bus */
{
handle->debug_print("dht11: bus init failed.\n"); /* bus init failed */
return 1; /* return error */
}
if (a_dht11_reset(handle) != 0) /* reset the chip */
{
handle->debug_print("dht11: reset failed.\n"); /* reset failed */
(void)handle->bus_deinit(); /* close bus */
return 4; /* return error */
}
handle->inited = 1; /* flag finish initialization */
return 0; /* success return 0 */
}
/**
* @brief close the chip
* @param[in] *handle points to a dht11 handle structure
* @return status code
* - 0 success
* - 1 bus deinit failed
* - 2 handle is NULL
* - 3 handle is not initialized
* @note none
*/
uint8_t dht11_deinit(dht11_handle_t *handle)
{
if (handle == NULL) /* check handle */
{
return 2; /* return error */
}
if (handle->inited != 1) /* check handle initialization */
{
return 3; /* return error */
}
if (handle->bus_deinit() != 0) /* close bus */
{
handle->debug_print("dht11: deinit failed.\n"); /* deinit failed */
return 1; /* return error */
}
handle->inited = 0; /* flag close */
return 0; /* success return 0 */
}
/**
* @brief get chip's information
* @param[out] *info points to a dht11 info structure
* @return status code
* - 0 success
* - 2 handle is NULL
* @note none
*/
uint8_t dht11_info(dht11_info_t *info)
{
if (info == NULL) /* check handle */
{
return 2; /* return error */
}
memset(info, 0, sizeof(dht11_info_t)); /* initialize dht11 info structure */
strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
strncpy(info->interface, "GPIO", 8); /* copy interface name */
info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
info->max_current_ma = MAX_CURRENT; /* set maximum current */
info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
info->driver_version = DRIVER_VERSION; /* set driver version */
return 0; /* success return 0 */
}
driver_dht11_interface.h
#ifndef __DRIVER_DHT11_INTERFACE_H__
#define __DRIVER_DHT11_INTERFACE_H__
#include "driver_dht11.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* @brief interface bus init
* @return status code
* - 0 success
* - 1 bus init failed
* @note none
*/
uint8_t dht11_interface_init(void);
/**
* @brief interface bus deinit
* @return status code
* - 0 success
* - 1 bus deinit failed
* @note none
*/
uint8_t dht11_interface_deinit(void);
/**
* @brief interface bus read
* @param[out] *value points to a value buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t dht11_interface_read(uint8_t *value);
/**
* @brief interface bus write
* @param[in] value is the written value
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t dht11_interface_write(uint8_t value);
/**
* @brief interface delay ms
* @param[in] ms
* @note none
*/
void dht11_interface_delay_ms(uint32_t ms);
/**
* @brief interface delay us
* @param[in] us
* @note none
*/
void dht11_interface_delay_us(uint32_t us);
/**
* @brief interface enable the interrupt
* @note none
*/
void dht11_interface_enable_irq(void);
/**
* @brief interface disable the interrupt
* @note none
*/
void dht11_interface_disable_irq(void);
/**
* @brief interface print format data
* @param[in] fmt is the format data
* @note none
*/
void dht11_interface_debug_print(const char *const fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
driver_dht11_interface.c
#include "driver_dht11_interface.h"
// static uint32_t GPIOC_IDR_ADDR = (((0x40000000UL + 0x00020000UL) + 0x0800UL) + 0x0010UL);
// static uint32_t GPIOC_ODR_ADDR = (((0x40000000UL + 0x00020000UL) + 0x0800UL) + 0x0014UL);
/**
* @brief interface bus init
* @return status code
* - 0 success
* - 1 bus init failed
* @note none
*/
uint8_t dht11_interface_init(void)
{
HAL_GPIO_WritePin(DHT11_Data_GPIO_Port, DHT11_Data_Pin, GPIO_PIN_SET);
return 0;
}
/**
* @brief interface bus deinit
* @return status code
* - 0 success
* - 1 bus deinit failed
* @note none
*/
uint8_t dht11_interface_deinit(void)
{
/* gpio deinit */
HAL_GPIO_DeInit(DHT11_Data_GPIO_Port, DHT11_Data_Pin);
return 0;
}
/**
* @brief interface bus read
* @param[out] *value points to a value buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t dht11_interface_read(uint8_t *value)
{
*value = HAL_GPIO_ReadPin(DHT11_Data_GPIO_Port, DHT11_Data_Pin);
return 0;
}
/**
* @brief interface bus write
* @param[in] value is the written value
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t dht11_interface_write(uint8_t value)
{
if (value)
{
HAL_GPIO_WritePin(DHT11_Data_GPIO_Port, DHT11_Data_Pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(DHT11_Data_GPIO_Port, DHT11_Data_Pin, GPIO_PIN_RESET);
}
return 0;
}
/**
* @brief interface delay ms
* @param[in] ms
* @note none
*/
void dht11_interface_delay_ms(uint32_t ms)
{
delay_ms(ms);
}
/**
* @brief interface delay us
* @param[in] us
* @note none
*/
void dht11_interface_delay_us(uint32_t us)
{
delay_us(us);
}
/**
* @brief interface enable the interrupt
* @note none
*/
void dht11_interface_enable_irq(void)
{
/* 内联函数 用于直接操作处理器的中断控制寄存器 开启全局中断 恢复所有已启用的中断 */
__enable_irq();
}
/**
* @brief interface disable the interrupt
* @note none
*/
void dht11_interface_disable_irq(void)
{
/* 内联函数 用于直接操作处理器的中断控制寄存器 禁用全局中断 禁用所有已启用的中断请求(不包括异常,如硬故障) */
__disable_irq();
}
/**
* @brief interface print format data
* @param[in] fmt is the format data
* @note none
*/
void dht11_interface_debug_print(const char *const fmt, ...)
{
printf(fmt);
}
driver_dht11_test.h
#ifndef __DRIVER_DHT11_TEST_H__
#define __DRIVER_DHT11_TEST_H__
#include "driver_dht11_interface.h"
#ifdef __cplusplus
extern "C"{
#endif
/**
* @brief read test
* @param[in] times is the test times
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t dht11_read_test(uint32_t times);
#ifdef __cplusplus
}
#endif
#endif
driver_dht11_test.c
#include "driver_dht11_test.h"
static dht11_handle_t gs_handle; /**< dht11 handle */
/**
* @brief read test
* @param[in] times is the test times
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t dht11_read_test(uint32_t times)
{
uint8_t res;
uint32_t i;
uint16_t temperature_raw;
uint16_t humidity_raw;
float temperature;
uint8_t humidity;
dht11_info_t info;
/* link interface function */
DRIVER_DHT11_LINK_INIT(&gs_handle, dht11_handle_t);
DRIVER_DHT11_LINK_BUS_INIT(&gs_handle, dht11_interface_init);
DRIVER_DHT11_LINK_BUS_DEINIT(&gs_handle, dht11_interface_deinit);
DRIVER_DHT11_LINK_BUS_READ(&gs_handle, dht11_interface_read);
DRIVER_DHT11_LINK_BUS_WRITE(&gs_handle, dht11_interface_write);
DRIVER_DHT11_LINK_DELAY_MS(&gs_handle, dht11_interface_delay_ms);
DRIVER_DHT11_LINK_DELAY_US(&gs_handle, dht11_interface_delay_us);
DRIVER_DHT11_LINK_ENABLE_IRQ(&gs_handle, dht11_interface_enable_irq);
DRIVER_DHT11_LINK_DISABLE_IRQ(&gs_handle, dht11_interface_disable_irq);
DRIVER_DHT11_LINK_DEBUG_PRINT(&gs_handle, dht11_interface_debug_print);
/* get dht11 information */
res = dht11_info(&info);
if (res != 0)
{
dht11_interface_debug_print("dht11: get info failed.\n");
return 1;
}
else
{
/* print dht11 information */
dht11_interface_debug_print("dht11: chip is %s.\n", info.chip_name);
// dht11_interface_debug_print("dht11: manufacturer is %s.\n", info.manufacturer_name);
// dht11_interface_debug_print("dht11: interface is %s.\n", info.interface);
// dht11_interface_debug_print("dht11: driver version is %d.%d.\n", info.driver_version / 1000, (info.driver_version % 1000) / 100);
// dht11_interface_debug_print("dht11: min supply voltage is %0.1fV.\n", info.supply_voltage_min_v);
// dht11_interface_debug_print("dht11: max supply voltage is %0.1fV.\n", info.supply_voltage_max_v);
// dht11_interface_debug_print("dht11: max current is %0.2fmA.\n", info.max_current_ma);
// dht11_interface_debug_print("dht11: max temperature is %0.1fC.\n", info.temperature_max);
// dht11_interface_debug_print("dht11: min temperature is %0.1fC.\n", info.temperature_min);
}
/* start basic read test */
dht11_interface_debug_print("dht11: start read test.\n");
/* dht11 init */
res = dht11_init(&gs_handle);
if (res != 0)
{
dht11_interface_debug_print("dht11: init failed.\n");
return 1;
}
/* delay 2000 ms for read */
dht11_interface_delay_ms(2000);
for (i = 0; i < times; i++)
{
/* read temperature and humidity */
res = dht11_read_temperature_humidity(&gs_handle, (uint16_t *)&temperature_raw, (float *)&temperature, (uint16_t *)&humidity_raw, (uint8_t *)&humidity);
if (res != 0)
{
dht11_interface_debug_print("dht11: read failed.\n");
(void)dht11_deinit(&gs_handle);
return 1;
}
/* print result */
dht11_interface_debug_print("dht11: temperature_raw: %dC.\n", temperature_raw);
dht11_interface_debug_print("dht11: humidity_raw: %dC.\n", humidity_raw);
dht11_interface_debug_print("dht11: temperature: %.01fC.\n", temperature);
dht11_interface_debug_print("dht11: humidity: %d%%.\n", humidity);
/* delay 2000 ms*/
dht11_interface_delay_ms(2000);
}
/* finish basic read test and exit */
dht11_interface_debug_print("dht11: finish read test.\n");
(void)dht11_deinit(&gs_handle);
return 0;
}
总结
《HAL快速入门与项目实战(基于DshanMCU-F407)_V1.0》中已经有对DHT11模块的详细讲解,这里对驱动程序进行了简单的复写。
能力有限,有错误地方欢迎指正。