HIH8121温湿度传感器代码基于STM32 HAL库
HIH8121传感器简介
HIH8121
是霍尼韦尔公司生产的测量温湿度参数一体的传感器,测量范围满足湿度:0-100%
温度:-40-125℃
,湿度测量误差±2%
,温度测量误差±0.5℃
。四引脚封装,分别是电源、接地、IIC总线的两条数据线,在使用绘制PCB时要尽量避免与发热器件靠近。驱动代码基于STM32 HAL
库编写,除微秒延时函数未给出(需要自己实现无法统一给出,根据自身单片机主频大小、是否采用RTOS
自己给出接口),驱动代码如下(代码适用于所有HIH8000
系列传感器):
驱动代码.c
#include "HIH8121.h"
THDATA HIH8121_Data;
static void IIC_start(void);
static void IIC_stop(void);
static uint8_t IIC_wait_ACK(void);
static void IIC_Ack(void);
static void IIC_NAck(void);
static void IIC_Send_Byte(uint8_t txd);
static uint8_t IIC_Read_Byte(unsigned char ack);
static void HIH8121_change_SDA_IN(void);
static void HIH8121_change_SDA_OUT(void);
//IIC引脚初始化
void HIH8121_IO_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
//初始化引脚 推挽输出 默认输出高电平
GPIO_InitStruct.Pin = HIH8121_SCL_GPIO_Pin | HIH8121_SDA_GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(HIH8121_SDA_GPIO, &GPIO_InitStruct);
}
//向传感器写入数据
uint8_t HIH8121_write(uint8_t w_data)//HIH8121_ADDRESS
{
uint32_t time_out = 0;
IIC_start();
IIC_Send_Byte(w_data);//HIH8121_ADDRESS
if(IIC_wait_ACK() == 1)
{
return 1;
}
IIC_stop();
return 0;
}
//从传感器读取数据
uint8_t HIH8121_read(uint8_t *read_buff)
{
IIC_start();
IIC_Send_Byte(HIH8121_ADDRESS_R);
if(IIC_wait_ACK() == 1)
{
return 1;
}
*read_buff = IIC_Read_Byte(1);
*(read_buff+1) = IIC_Read_Byte(1);
*(read_buff+2) = IIC_Read_Byte(1);
*(read_buff+3) = IIC_Read_Byte(0);
IIC_stop();
return 0;
}
//改变IIC数据引脚为输入
static void HIH8121_change_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = HIH8121_SDA_GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(HIH8121_SDA_GPIO, &GPIO_InitStruct);
}
//改变IIC数据引脚为输出
static void HIH8121_change_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = HIH8121_SDA_GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(HIH8121_SDA_GPIO, &GPIO_InitStruct);
}
//读取HIH8121传感器数据 并解析存储 返回0解析成功 返回1解析失败
uint8_t read_HIH8121(void)
{
uint8_t HIH8121_status_flag;
if(HIH8121_read(HIH8121_Data.HIH8121_IIC_buff) == 1)
{
return 1;
}
HIH8121_status_flag = HIH8121_Data.HIH8121_IIC_buff[0]>>6;
if(HIH8121_status_flag == 0)
{
HIH8121_Data.Humidity_Raw = (((uint16_t)(HIH8121_Data.HIH8121_IIC_buff[0]&0x3f))<<8) + HIH8121_Data.HIH8121_IIC_buff[1];
HIH8121_Data.Temperature_Raw = (((uint16_t)(HIH8121_Data.HIH8121_IIC_buff[2]))<<6) + (HIH8121_Data.HIH8121_IIC_buff[3]>>2);
HIH8121_Data.Humidity = (((float)HIH8121_Data.Humidity_Raw)/16382.0)*100.0;
HIH8121_Data.Temperature = (((float)HIH8121_Data.Temperature_Raw)/16382.0)*165.0-40;
}
return 0;
}
//以下是软件模拟IIC驱动函数
static void IIC_start(void)
{
HIH8121_change_SDA_OUT();
HIH8121_SDA_H;
HIH8121_SCL_H;
HIH8121_delay_us(4);
HIH8121_SDA_L;
HIH8121_delay_us(4);
HIH8121_SCL_L;
}
static void IIC_stop(void)
{
HIH8121_change_SDA_OUT();
HIH8121_SCL_L;
HIH8121_SDA_L;
HIH8121_delay_us(4);
HIH8121_SCL_H;
HIH8121_SDA_H;
HIH8121_delay_us(4);
}
static uint8_t IIC_wait_ACK(void)
{
uint8_t wait_time = 0;
HIH8121_change_SDA_IN();
HIH8121_SDA_H;
HIH8121_delay_us(1);
HIH8121_SCL_H;
HIH8121_delay_us(1);
while(HIH8121_READ_SDA)
{
wait_time++;
if(wait_time>250)
{
IIC_stop();
return 1;
}
}
HIH8121_SCL_L;
return 0;
}
static void IIC_Ack(void)
{
HIH8121_SCL_L;
HIH8121_change_SDA_OUT();
HIH8121_SDA_L;
HIH8121_delay_us(2);
HIH8121_SCL_H;
HIH8121_delay_us(2);
HIH8121_SCL_L;
}
//不产生ACK应答
static void IIC_NAck(void)
{
HIH8121_SCL_L;
HIH8121_change_SDA_OUT();
HIH8121_SDA_H;
HIH8121_delay_us(2);
HIH8121_SCL_H;
HIH8121_delay_us(2);
HIH8121_SCL_L;
}
static void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
HIH8121_change_SDA_OUT();
HIH8121_SCL_L;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
HAL_GPIO_WritePin(HIH8121_SDA_GPIO, HIH8121_SDA_GPIO_Pin, ((txd&0x80)>>7));
// IIC_SDA=(txd&0x80)>>7;
txd<<=1;
HIH8121_delay_us(1); //对TEA5767这三个延时都是必须的
HIH8121_SCL_H;
HIH8121_delay_us(1);
HIH8121_SCL_L;
HIH8121_delay_us(1);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
HIH8121_change_SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
HIH8121_SCL_L;
HIH8121_delay_us(2);
HIH8121_SCL_H;
receive<<=1;
if(HIH8121_READ_SDA)
receive += 1;
HIH8121_delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
驱动代码.h
#ifndef __HIH8121_H
#define __HIH8121_H
#include "stm32f4xx_hal.h"
/*
PB8 SCL 定义IIC SCL引脚
PB9 SDA 定义IIC SDA引脚
*/
#define HIH8121_SCL_GPIO GPIOB
#define HIH8121_SCL_GPIO_Pin GPIO_PIN_8
#define HIH8121_SDA_GPIO GPIOB
#define HIH8121_SDA_GPIO_Pin GPIO_PIN_9
#define HIH8121_READ_SDA HAL_GPIO_ReadPin(HIH8121_SDA_GPIO,HIH8121_SDA_GPIO_Pin)
#define HIH8121_SCL_H HAL_GPIO_WritePin(HIH8121_SCL_GPIO, HIH8121_SCL_GPIO_Pin, GPIO_PIN_SET);
#define HIH8121_SCL_L HAL_GPIO_WritePin(HIH8121_SCL_GPIO, HIH8121_SCL_GPIO_Pin, GPIO_PIN_RESET);
#define HIH8121_SDA_H HAL_GPIO_WritePin(HIH8121_SDA_GPIO, HIH8121_SDA_GPIO_Pin, GPIO_PIN_SET);
#define HIH8121_SDA_L HAL_GPIO_WritePin(HIH8121_SDA_GPIO, HIH8121_SDA_GPIO_Pin, GPIO_PIN_RESET);
#define HIH8121_Original_ADDRESS 0x27 //original address
#define HIH8121_ADDRESS 0x4E // <<1 address
#define HIH8121_ADDRESS_R 0x4F //for reading
//注意****************
//微秒延时函数需要自己实现 根据单片机采用M3 M4 M7或者是否采用RTOS
//灵活实现
#define HIH8121_delay_us(h_t) delay_us(h_t)
typedef struct THDATA
{
unsigned char HIH8121_IIC_buff[8]; //IIC读取到的原始数据 包含数据状态和温湿度数据
unsigned short Humidity_Raw; //解析到的传感器寄存器原始湿度值
unsigned short Temperature_Raw; //解析到的传感器寄存器原始温度值
float Humidity; //湿度最终计算结果
float Temperature; //温度最终计算结
}THDATA;
extern THDATA HIH8121_Data;
void HIH8121_IO_init(void);
uint8_t HIH8121_write(uint8_t w_data);
uint8_t HIH8121_read(uint8_t *read_buff);
uint8_t read_HIH8121(void);
#endif
main函数
void main(void)
{
uint8_t tmp_count=0;
int8_t ret_val;
HAL_Init(); //HAL库初始化
SystemClock_Config(); //单片机时钟配置
HIH8121_IO_init(); //IIC引脚初始化
HAL_Delay(5); //短暂延时 要不要无关紧要
while(1)
{
HAL_Delay(5);
tmp_count++;
if(tmp_count == 160) //延时计数到达800ms时
{
HIH8121_write(HIH8121_ADDRESS); //发送读取指令 传感器进行数据转换
}
if(tmp_count >= 200) // 延时计数到达1000ms时 开始进行数据读取 给温湿度传感器200ms的数据准备时间
{
ret_val = read_HIH8121(); //读取传感器数据 数据存储在HIH8121_Data结构体中
tmp_count = 0; //延时计数清零
}
}
}