HDC1080 驱动程序代码(C语言版)

HDC1080 驱动程序代码(C语言版),第1张

在列出HDC1080温湿度传感器驱动程序关键代码之前,请允许我先废话几句:

  1. CSDN上有关HDC1080驱动代码的高阅读量博客只有两篇,且两篇博客内都不提供代码!而是在其中附上了需要积分才能下载代码的链接。


    吐了。


  2. GitHub上有关HDC1080驱动代码的STM32版只有两篇。


    一篇代码使用STM32的HAL库写的,在I2C的使用上封装程度太高,看不到通信中的关键细节。


    另一篇代码使用了大量的OLED界面 *** 作,整体代码过于冗余,并且在HDC1080的I2C驱动上写的不清晰。


  3. TI公司的HDC1080官方芯片手册,在HDC1080驱动步骤中的第二步和第三步上写的及其令人费解,以至于我花了两天不断思考这两步究竟是要做什么 *** 作。


下面进入正文。


温湿度数据

最终结果截图如下,temp温度在25℃左右,humi湿度在51%RH。


当我将手指放在HDC1080表面时,temp温度逐渐升高至27℃左右,而humi湿度显示为0,这可能是由于HDC1080表面探测湿度的金色元件被我的手指完全遮挡所导致。


之后,当我将手指移出HDC1080,temp温度和humi湿度逐渐回归正常数值。



驱动代码 HDC1080.h

首先,我使用的是STM32F103C8T6芯片,采用Keil 5编程软件,通过软件I2C协议和HDC1080芯片进行通信。


软件I2C中,SCL = PB0,SDA = PB1。


在HDC1080.h中我做了如下三部分的定义,

  1. HDC1080 软件I2C的接口定义
  2. HDC1080 各寄存器地址
  3. 软件I2C函数和HDC1080相关读取函数

具体代码如下:

#ifndef __HDC1080_H__
#define __HDC1080_H__
#include "sys.h"

// HDC1080 sensor port: PB0 - PB1
#define HDC1080_PORT	GPIOB	

#define HDC1080_SCL		GPIO_Pin_0
#define HDC1080_SDA		GPIO_Pin_1	

#define HDC1080_SCL_H          HDC1080_PORT->BSRR = HDC1080_SCL //set to 1
#define HDC1080_SCL_L          HDC1080_PORT->BRR  = HDC1080_SCL //reset to 0
#define HDC1080_SDA_H          HDC1080_PORT->BSRR = HDC1080_SDA
#define HDC1080_SDA_L          HDC1080_PORT->BRR  = HDC1080_SDA

#define HDC1080_SCL_Status     HDC1080_PORT->IDR  & HDC1080_SCL //IDR是查看引脚电平状态
#define HDC1080_SDA_Status     HDC1080_PORT->IDR  & HDC1080_SDA

// The Chip parameters we use.
#define HDC1080_TempAddress         0x00
#define HDC1080_HumiAddress         0x01
#define HDC1080_Configuration       0x02
#define HDC1080_ManufactID          0xFE
#define HDC1080_DeviceID            0xFF

#define HDC1080_Write_Address		0x80
#define HDC1080_Read_Address        0x81


// I2C initial 
void HDC1080_I2C_GPIO_Configuration(void);

void I2C4_delay(void);

int  I2C4_Start(void);
void I2C4_Stop(void);

void I2C4_SDA_IN(void);
void I2C4_SDA_OUT(void);

static void I2C4_Ack(void);
static void I2C4_NoAck(void);
uint8_t I2C4_GetAck(void);

void    I2C4_WriteByte(uint8_t Data);
uint8_t I2C4_ReadByte(uint8_t ack);

int HDC1080_I2C4_WriteByte(uint8_t Reg_Addr, uint8_t Data);
int HDC1080_I2C4_WriteBuffer(uint8_t Reg_Addr, uint8_t *pBuffer, uint8_t NumByteToWrite);

int HDC1080_I2C4_ReadByte(uint8_t Reg_Addr, uint8_t *Data);
int HDC1080_I2C4_ReadBuffer(uint8_t Reg_Addr, uint8_t *pBuffer, uint8_t NumByteToRead); 

void HDC1080_Start(void);
uint16_t HDC1080_Result(char ch);
void HDC1080_Caculate(uint16_t ut, uint16_t uh, float *rt, float *rh);

#endif
驱动代码 HDC1080.c

下面讲解在驱动HDC1080过程中的核心代码和逻辑,首先我们看一下TI官方芯片手册中给出的通信过程:

对于第一步配置HDC1080的工作模式和第四步读取温湿度数据,这两步理解起来很容易。


而最难以理解的是第二步和第三步,这两句话是什么意思?我们该怎么做通信?我本以为第二步和第三步是做两个独立的通信动作。


但实际上,第二部和第三步合起来只是做了一个通信动作。


我们来看如下通信流程图:

在这张流程图中,I2C写1次数据完成了芯片手册中提到的第一步,I2C读一次数据完成了芯片手册中提到的的

二、

三、四步。


我们都知道I2C在读/写设备数据的过程中,需要经过主从模式的转换。


也就是说,STM32使用I2C读数据前,首先将自己设置为主设备,之后进行写地址 *** 作,也就是流程图中的Write 0x80 和 Write 0x00。


完成后,再次进行写 *** 作,也就是流程图中的Write 0x81,这里需注意0x80和0x81的含义。


然后将自己的工作模式转换为从设备,开始进入数据接收状态读取主设备发送来的数据。


下面我们再次回顾HDC1080芯片手册中设备通信过程的2、3、4条:
2. Trigger the measurements by executing a pointer write transaction with the address pointer set to 0x00.
3. Wait for the measurements to complete, based on the conversion time.
4. Read the output data。


我们发现整个2、3、4条的通信过程,即和流程图中的I2C读一次数据的过程完全对应。


其中第3条通信动作,Wait for the measurements to complete,是夹在I2C读一次数据过程之中的。


搞清楚这一步,下面再向寄存器读取温湿度数据就没有问题了。


下面提供HDC1080.c中的关键通信代码,其中最重要的代码是 HDC1080_I2C4_ReadBuffer 函数,请多注意。


/           HDC1080 Coding       //
void HDC1080_Start(void)
{
	/* uint8_t ManuID[2];
	HDC1080_I2C4_ReadBuffer(HDC1080_ManufactID,ManuID,2);//read 0x5449 is ok! */
	
	uint8_t buf[4];
	buf[0] = 0x10; //config temp and humi
	buf[1] = 0x00; //both 14 bit

    HDC1080_I2C4_WriteBuffer(HDC1080_Configuration,buf,2);
}

uint16_t HDC1080_Result(char ch)
{
	uint16_t temp,humi;
	uint8_t buf[4];
	
	HDC1080_I2C4_ReadBuffer(HDC1080_TempAddress,buf,4);

	temp = buf[0] << 8;
	temp |= buf[1];

	humi = buf[2] << 8;
	humi |= buf[3];

	if (ch == 'T') //ch字符用来进行温度和湿度的选择性输出
	{
		return temp;
	}
	else if (ch == 'H')
	{
		return humi;
	}
	else{
		return 0;
	}
}

void HDC1080_Caculate(uint16_t ut, uint16_t uh, float *rt, float *rh)
{
		//ut 和 uh 为从HDC1080中读取出的原始温湿度值,这里根据芯片手册中的公式进行转换。


*rt = ut / pow(2.0, 16.0) * 165.0 - 40.0; //'C *rh = uh / pow(2.0, 16.0) * 100.0; //%RH } int HDC1080_I2C4_ReadBuffer(uint8_t Reg_Addr, uint8_t *pBuffer, uint8_t NumByteToRead){ uint8_t i; uint8_t tag;//选择性回应Ack I2C4_Start(); I2C4_WriteByte(HDC1080_Write_Address); if(!I2C4_GetAck())// 有slave ack的响应 { I2C4_Stop(); return DISABLE; } I2C4_WriteByte(Reg_Addr); if(!I2C4_GetAck()) { I2C4_Stop(); return DISABLE; } delay_ms(20);//等待温湿度数据转换 I2C4_Start();//更改通信模式,主机从发送变为接收 I2C4_WriteByte(HDC1080_Read_Address); if(!I2C4_GetAck())// 有slave ack的响应 { I2C4_Stop(); return DISABLE; } for(i=0; i<NumByteToRead; i++) { tag = (i == NumByteToRead-1) ? 0 : 1; pBuffer[i] = I2C4_ReadByte(tag); } I2C4_Stop(); //在这个位置统一停止 return 1; }

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/564540.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-06
下一篇 2022-04-06

发表评论

登录后才能评论

评论列表(0条)

保存