1.开发背景
一款可以检测环境温度和湿度的传感器,外部接口是通用 IIC 接口,并且采集数据的速度比较有限,特别是数据的位数比较高的情况下,需要毫秒级别的等待时间。
2.开发需求
获取传感器的温度和湿度,循环打印
3.开发环境
window10 + MDK + STM32F103C8T6
4.详细设计
4.1 关键寄存器
如上图所示为可读写的寄存器,其中 0xFB~0xFF 是读取 ID 相关的,可以上电后读取 ID 判断芯片是否存在。0x00 可以读取温度,0x01可以读取湿度,0x02主要是写配置信息。
和芯片沟通的桥梁只有IIC一个接口,每个寄存器的数据是16bit,即 2 个字节下面是读写时序
4.2 控制流程
4.2.1 读设备ID 0xFF
设备 ID 是固定的 0x1050,如果读取的 ID 不一致就需要排查 IIC 是否正确了。
4.2.2 写配置 0x02
配置关键信息,一般在上电后配置一次就可以了,这里主要配置 MODE 设置 1,采集温度和湿度。其他位可以保持 0 即可。当然,如果需要配置采集可数据位可以操作 TRES 和 HRES,低位数可以获得更快的采集速度。
4.2.3 读取温度 0x00
读取寄存器后直接套用公式即可。但是这里涉及到一个问题,就是采集数据是需要时间的,不是立刻就能采集到数据的,根据不同位数的采集时间,采集数据需要几毫秒到十几毫秒不等。
因此需要对数据未采集完成时返回的 NACK 判断处理,延时一段时间后继续读取,但是只能读取,不能重新对寄存器 0x00 写操作,每次的写操作都是一次重新采集的开始,这样是一直采集不到数据的。
4.2.4 读取湿度 0x01
读取湿度和读取温度类似,照搬即可。
4.3 软件实现
4.3.1 IIC 接口
#ifndef CSP_IIC_H
#define CSP_IIC_H/* 数组索引 不要随便改 */
typedef enum
{eIic1 = 0,eIic2 ,eIic3 ,}EnumIic_t;void cIic_Init(void);/* 对地址的设备通讯 */
int cIic_ReadData(EnumIic_t eIic, unsigned char address, unsigned char *pData, int size);
int cIic_WriteData(EnumIic_t eIic, unsigned char address, unsigned char *pData, int size);
int cIic_WriteRegister(EnumIic_t eIic, unsigned char address, unsigned char reg, unsigned char *pData, int size);#endif
4.3.2 HDC1080头文件
#ifndef BSP_HDC1080_H
#define BSP_HDC1080_Hint bHdc1080_Init(void);
unsigned short bHdc1080_GetDeviceId(void);
unsigned short bHdc1080_GetManufactId(void);
float bHdc1080_GetTemperature(void);
float bHdc1080_GetHumid(void);/* 指定延时接口 */
void bHdc1080_SetDelayMsFunction(void function(unsigned int));#endif
4.3.3 HDC1080源文件
#include "bspHdc1080.h"#include <stdio.h>#include "cspDwt.h"
#include "cspIic.h"#include "modAlgorithm.h"/* 固定 ID */
#define HDC1080_DEVICE_ID (0x1050)
#define HDC1080_MANUFACT_ID (0x5449)/* 传感器地址 */
#define HDC1080_ADDRESS (0x40)/* 传感器寄存器地址 */
#define HDC1080_REG_TEMPERATURE (0x00)
#define HDC1080_REG_HUMID (0x01)
#define HDC1080_REG_CONFIG (0x02)
#define HDC1080_REG_MANUFACT_ID (0xFE)
#define HDC1080_REG_DEVICE_ID (0xFF)typedef struct
{unsigned short hres : 2; // 湿度数据位数 0x00:14bit; 0x01:11bit; 0x10:8bitunsigned short tres : 1; // 温度数据位数 0x00:14bit; 0x01:11bit;unsigned short btst : 1; // 电池状态 0:> 2.8V 1:< 2.8Vunsigned short mode : 1; // 0:二选1; 1:一起,温度在前unsigned short heat: 1; // 0unsigned short reserved1 : 1; // 0unsigned short rst : 1; // 1复位unsigned short reserved2 : 8; // 0}Hdc1080_Config_t;typedef struct
{void (*delayMs) (unsigned int ms);}Ctrl_t;static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;/* 读数据 */
static int Hdc1080_ReadRegister(unsigned char reg, unsigned char *pData, int size)
{if (cIic_WriteData(eIic1, HDC1080_ADDRESS, ®, sizeof(reg)) < 0){return -1;}char readCnt = 10;while (readCnt > 0){if (cIic_ReadData(eIic1, HDC1080_ADDRESS, pData, size) >= 0){return 0;}/* 延时一段时间 */if (p->delayMs == NULL){for (int i = 0; i < 50000; i++); // 72M下大概 10ms 10000次}else{p->delayMs(5);}readCnt--;}return -1;
}/* 写数据 */
static int Hdc1080_WriteRegister(unsigned char reg, unsigned char *pData, int size)
{return cIic_WriteRegister(eIic1, HDC1080_ADDRESS, reg, pData, size);
}/* 初始化 */
int bHdc1080_Init(void)
{Hdc1080_Config_t strConfig = {0};strConfig.btst = 0;strConfig.heat = 0;strConfig.hres = 0;strConfig.mode = 0;strConfig.rst = 1; strConfig.tres = 0;Hdc1080_WriteRegister(HDC1080_REG_CONFIG, (unsigned char *)&strConfig, sizeof(strConfig));/* 设备 ID 检测 */if (bHdc1080_GetDeviceId() != HDC1080_DEVICE_ID){printf("%s get device id failed\r\n", __func__);return -1;}/* 设备 ID 检测 */if (bHdc1080_GetManufactId() != HDC1080_MANUFACT_ID){printf("%s get manufact id failed\r\n", __func__);return -1;}return 0;
}/* 获取设备 ID */
unsigned short bHdc1080_GetDeviceId(void)
{/* 读取寄存器ID */unsigned short deviceId = 0;Hdc1080_ReadRegister(HDC1080_REG_DEVICE_ID, (unsigned char *)&deviceId, sizeof(deviceId));/* 调转 高低位 */mAlgorithm_SwapEndianData(&deviceId, sizeof(deviceId));return deviceId;
}/* 获取生产ID */
unsigned short bHdc1080_GetManufactId(void)
{/* 读取寄存器ID */unsigned short manufactId = 0;Hdc1080_ReadRegister(HDC1080_REG_MANUFACT_ID, (unsigned char *)&manufactId, sizeof(manufactId));/* 调转 高低位 */mAlgorithm_SwapEndianData(&manufactId, sizeof(manufactId));return manufactId;
}/* 获取温度 */
float bHdc1080_GetTemperature(void)
{/* 读取寄存器ID */unsigned short tempReg = {0};Hdc1080_ReadRegister(HDC1080_REG_TEMPERATURE, (unsigned char *)&tempReg, sizeof(tempReg));/* 调转 高低位 低 2 位是0 */mAlgorithm_SwapEndianData(&tempReg, sizeof(tempReg));float temp = (float)tempReg / 0x10000 * 165 - 40;return temp;
}/* 获取湿度 */
float bHdc1080_GetHumid(void)
{/* 读取寄存器ID */unsigned short humidReg = {0};Hdc1080_ReadRegister(HDC1080_REG_HUMID, (unsigned char *)&humidReg, sizeof(humidReg));/* 调转 高低位 低 2 位是0 */mAlgorithm_SwapEndianData(&humidReg, sizeof(humidReg));float humid = (float)humidReg / 0x10000 * 100;return humid;
}/* 指定延时接口 */
void bHdc1080_SetDelayMsFunction(void function(unsigned int))
{p->delayMs = function;
}