适用平台
- STM32、M5311(需电平转换电路)、DA14531 等无特定要求
驱动优势
- 实现与接口分离(对象封装)
- 平台移植层分离(GPIO 工作模式)
- 总线自动管理(总线空闲时低功耗处理)
- 不同工作电压的矫正系数管理
特别说明
- 本文件未对 SHT10 做系统性介绍,需要使用者自行查阅规格书了解
使用者仅需要修改 .h 文件中的系统移植层部分
- 连接的 GPIO (SCK, SDA)
- SHT10 的工作电压
文件:main.c
#include "bsp_sht10.h"
int main()
{
float temp = 0.0f;
float humi = 0.0f;
float dew_poiusernt = 0.0f;
SHT_HandlerSdef *sht_handler = sht_init(); // 参数初始化
for (;;)
{
if (sht_handler->user_getTempAndHumi(&temp, &humi)) // 温湿度读取
{
printf("temp:%f, humi:%f\n", temp, humi);
}
if (sht_handler->user_getDewPoiusernt()) // 露点读取
{
printf("DewPoiusernt:%f\n", dew_poiusernt);
}
}
}
文件:bsp_sht10.h
#ifndef BSP_SHT10_H
#define BSP_SHT10_H
/** Inlcude --------------------------------------------------*/
#include
/**
* @brief 系统移植层
* @{
*/
#include "gpio.h"
#define SHT10_DATA_PIN GPIO_PIN_1
#define SHT10_SCK_PIN GPIO_PIN_0
#define SHT10_DATA_PORT GPIO_PORT_0
#define SHT10_SCK_PORT GPIO_PORT_0
#define SHT10_DATA_H() GPIO_SetActive(SHT10_DATA_PORT, SHT10_DATA_PIN)
#define SHT10_DATA_L() GPIO_SetInactive(SHT10_DATA_PORT, SHT10_DATA_PIN)
#define SHT10_DATA_R() GPIO_GetPinStatus(SHT10_DATA_PORT, SHT10_DATA_PIN)
#define SHT10_SCK_H() GPIO_SetActive(SHT10_SCK_PORT, SHT10_SCK_PIN)
#define SHT10_SCK_L() GPIO_SetInactive(SHT10_SCK_PORT, SHT10_SCK_PIN)
#define sht10_pinConfig() {GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, OUTPUT, PID_GPIO, true);GPIO_ConfigurePin(SHT10_SCK_PORT, SHT10_SCK_PIN, OUTPUT, PID_GPIO, true);}
// 总线释放时的低功耗处理
#define sht10_pinRelease() {GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, INPUT, PID_GPIO, false);GPIO_ConfigurePin(SHT10_SCK_PORT, SHT10_SCK_PIN, INPUT, PID_GPIO, false);}
#define sht10_setDataOut() GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, OUTPUT, PID_GPIO, true)
#define sht10_setDataIn() GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, INPUT_PULLUP, PID_GPIO, false)
/*
__inline void sht10_pinConfig(void)
{
GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, OUTPUT, PID_GPIO, true);
GPIO_ConfigurePin(SHT10_SCK_PORT, SHT10_SCK_PIN, OUTPUT, PID_GPIO, true);
}
// 总线释放时的低功耗处理
__inline void sht10_pinRelease(void)
{
GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, INPUT, PID_SPI_DI, false);
GPIO_ConfigurePin(SHT10_SCK_PORT, SHT10_SCK_PIN, INPUT, PID_SPI_DI, false);
}
__inline void sht10_setDataOut(void)
{
GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, OUTPUT, PID_GPIO, true);
}
__inline void sht10_setDataIn(void)
{
GPIO_ConfigurePin(SHT10_DATA_PORT, SHT10_DATA_PIN, INPUT_PULLUP, PID_GPIO, false);
}
*/
/**
* @brief SHT10 当前的工作电压值(影响矫正系数)
*/
//#define SHT10_POWER_LEVEL_5V
//#define SHT10_POWER_LEVEL_4V
//#define SHT10_POWER_LEVEL_3_5V
#define SHT10_POWER_LEVEL_3V
//#define SHT10_POWER_LEVEL_2_5V
/**
* @}
*/
/**
* @brief SHT10 handler
*/
typedef struct
{
uint8_t (*user_reset)(void);
uint8_t (*user_getTempAndHumi)(float *temp, float *humi);
uint8_t (*user_getDewPoiusernt)(float *value);
}SHT_HandlerSdef;
/** Export function ------------------------------------*/
SHT_HandlerSdef* sht_init(void);
#endif
文件:bsp_sht10.c
/**
**************************************************
*@file bsp_sht10.c
*@brief SHT10 底层驱动文件
*@version v0.0.1
*@history
v0.0.1 2020/07/06 吴天送 正式发布
*************************************************
*/
/** Inlcude --------------------------------------------------*/
#include "bsp_sht10.h"
#include
/**Private macros ----------------------*/
//addr command r/w
#define SHT10_STATUS_REG_W 0x06 //000 0011 0
#define SHT10_STATUS_REG_R 0x07 //000 0011 1
#define SHT10_MEASURE_TEMP 0x03 //000 0001 1
#define SHT10_MEASURE_HUMI 0x05 //000 0010 1
#define SHT10_SOFTRESET 0x1E //000 1111 0
#define SHT10_NOACK 0
#define SHT10_ACK 1
#ifdef SHT10_POWER_LEVEL_5V
const float SHT10_D1 = -40.1;
#elif defined SHT10_POWER_LEVEL_4V
const float SHT10_D1 = -39.8;
#elif defined SHT10_POWER_LEVEL_3_5V
const float SHT10_D1 = -39.7;
#elif defined SHT10_POWER_LEVEL_3V
const float SHT10_D1 = -39.6;
#elif defined SHT10_POWER_LEVEL_2_5V
const float SHT10_D1 = -39.4;
#else
#error "没有指定SHT10工作电压"
#endif
typedef enum
{
SHT_Temp = 0u,
SHT_Humi
}SHT_ModeEdef;
/** Pravite function prototypes ------------------------------*/
static uint8_t sht10_writeByte(uint8_t data);
static uint8_t sht10_readByte(uint8_t is_ack);
static void sht10_transStart(void);
static void sht10_conReset(void);
static uint8_t sht10_reset(void);
static uint8_t sht10_measure(uint16_t *p_value, SHT_ModeEdef mode);
static uint8_t sht10_getTempAndHumi(float *temp, float *humi);
static uint8_t get_getDewPoint(float *value);
/** Pravite variable -----------------------------------------*/
static SHT_HandlerSdef g_sht_handler;
/** Applation */
/**
*@brief 重要数据注册及初始化
*@param none
*@retval none
*/
SHT_HandlerSdef* sht_init(void)
{
g_sht_handler.user_reset = sht10_reset;
g_sht_handler.user_getTempAndHumi = sht10_getTempAndHumi;
g_sht_handler.user_getDewPoiusernt = get_getDewPoint;
sht10_reset();
return &g_sht_handler;
}
/**
*@brief 延时函数 ( > 10us )
*@param none
*@retval none
*/
static void sht10_delay(void)
{
for (uint16_t i=0; i<100; ++i)
{ }
}
/**
*@brief 写一个字节
*@param data : 要写的字节
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t sht10_writeByte(uint8_t data)
{
uint8_t ret = 0;
sht10_setDataOut();
for(uint8_t i = 0x80; i > 0; i>>=1)
{
if(i & data)
SHT10_DATA_H();
else
SHT10_DATA_L();
sht10_delay();
SHT10_SCK_H();
sht10_delay();
SHT10_SCK_L();
sht10_delay();
}
sht10_setDataIn();
SHT10_SCK_H();
ret = SHT10_DATA_R();
SHT10_SCK_L();
return ret;
}
/**
*@brief 读取一个字节
*@param is_ack : 0 不应答 ; 1 应答
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t sht10_readByte(uint8_t is_ack)
{
uint8_t ret = 0;
sht10_setDataIn();
for(uint8_t i = 0x80; i > 0; i>>=1)
{
sht10_delay();
SHT10_SCK_H();
sht10_delay();
if(SHT10_DATA_R())
ret |= i;
SHT10_SCK_L();
}
sht10_setDataOut();
if(is_ack)
SHT10_DATA_L();
else
SHT10_DATA_H();
sht10_delay();
SHT10_SCK_H();
sht10_delay();
SHT10_SCK_L();
sht10_delay();
return ret;
}
/**
*@brief 开始传输信号
*@param none
*@retval none
*/
static void sht10_transStart(void)
{
sht10_setDataOut();
SHT10_DATA_H();
SHT10_SCK_L();
sht10_delay();
SHT10_SCK_H();
sht10_delay();
SHT10_DATA_L();
sht10_delay();
SHT10_SCK_L();
sht10_delay();
SHT10_SCK_H();
sht10_delay();
SHT10_DATA_H();
sht10_delay();
SHT10_SCK_L();
}
/**
*@brief 通讯复位
*@param none
*@retval none
*/
static void sht10_conReset(void)
{
sht10_setDataOut();
SHT10_DATA_H();
SHT10_SCK_L();
for(uint8_t i = 0; i < 9; i++)
{
SHT10_SCK_H();
sht10_delay();
SHT10_SCK_L();
sht10_delay();
}
sht10_transStart();
}
/**
*@brief 软复位
*@param none
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t sht10_reset(void)
{
uint8_t ret = 0;
sht10_pinConfig();
sht10_conReset();
ret = sht10_writeByte(SHT10_SOFTRESET);
sht10_pinRelease();
return ret;
}
/**
*@brief 温/湿度寄存器原始值读取
*@param p_value : 数据保存地址
*@param mode : SHT_Temp 温度 ; SHT_Humi 湿度
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t sht10_measure(uint16_t *p_value, SHT_ModeEdef mode)
{
uint8_t status = 0;
sht10_transStart();
switch(mode)
{
case SHT_Temp:
status = sht10_writeByte(SHT10_MEASURE_TEMP);
break;
case SHT_Humi:
status =sht10_writeByte(SHT10_MEASURE_HUMI);
break;
}
sht10_setDataIn();
if (status == 1)
{
sht10_conReset();
return 1;
}
for(uint32_t i = 0; i < 72000000; ++i)
if(SHT10_DATA_R() == 0) break;
if (SHT10_DATA_R() == 1)
{
sht10_conReset();
return 1;
}
uint8_t value_H = 0;
uint8_t value_L = 0;
value_H = sht10_readByte(SHT10_ACK);
value_L = sht10_readByte(SHT10_ACK);
sht10_readByte(SHT10_NOACK);
*p_value = (value_H << 8) | value_L;
return 0;
}
/**
*@brief 可读的温湿度读取
*@param temp : 温度值
*@param humi : 湿度值
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t sht10_getTempAndHumi(float *temp, float *humi)
{
const float d1 = SHT10_D1;
const float d2 = +0.01;
const float C1 = -2.0468;
const float C2 = +0.0367;
const float C3 = -0.0000015955;
const float T1 = +0.01;
const float T2 = +0.00008;
float rh_line = 0;
uint16_t temp_value_original = 0;
uint16_t humi_value_original = 0;
sht10_pinConfig();
if ((sht10_measure(&temp_value_original, SHT_Temp) != 0) || (sht10_measure(&humi_value_original, SHT_Humi) != 0))
{
sht10_pinRelease();
return 1;
}
rh_line = C1 + C2 * humi_value_original + C3 * humi_value_original * humi_value_original;
*temp = d1 + d2 * temp_value_original;
*humi = (*temp -25) * (T1 + T2 * humi_value_original) + rh_line;
sht10_pinRelease();
return 0;
}
/**
*@brief 计算露点
*@param value : 读取到的露点值
*@retval 0 成功
*@retval 其它 失败
*/
static uint8_t get_getDewPoint(float *value)
{
float temp = 0;
float humi = 0;
float logEx =0.0f;
sht10_pinConfig();
if (sht10_getTempAndHumi(&temp, &humi) != 0)
{
sht10_pinRelease();
return 1;
}
logEx = 0.66077 + 7.5 * temp / (237.3 + temp) + (log10(humi) - 2);
*value = ((0.66077 - logEx) * 237.3) / (logEx - 8.16077);
sht10_pinRelease();
return 0;
}