STM32之HTU21D温湿度传感器获取温湿度数据

文章目录[隐藏]

一、引脚

器件引脚

二、代码

iic.c文件

#include "iic.h"

/* 初始化模拟IIC
 *
 */
void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIOA时钟

	//GPIOB1,B2初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;	  //普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	  //上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);			  //初始化

	SCL_H;
	SDA_H;
}

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT(); //sda线输出
	SDA_H;
	SCL_H;
	IIC_Delay_us(4);
	SDA_L; //START:when CLK is high,DATA change form high to low
	IIC_Delay_us(4);
	SCL_L; //钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT(); //sda线输出
	SCL_L;
	SDA_L; //STOP:when CLK is high DATA change form low to high
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(1);
	SDA_H; //发送I2C总线结束信号
	IIC_Delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime = 0;
	SDA_IN(); //SDA设置为输入
	SDA_H;
	IIC_Delay_us(1);
	SCL_H;
	IIC_Delay_us(1);
	while (SDA_READ)
	{
		ucErrTime++;
		if (ucErrTime > 250)
		{
			IIC_Stop();
			return 1;
		}
	}
	SCL_L;
	IIC_Delay_us(30);
	return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
	SCL_L;
	SDA_OUT();
	SDA_L;
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(2);
	SCL_L;
}
//不产生ACK应答
void IIC_NAck(void)
{
	SCL_L;
	SDA_OUT();
	SDA_H;
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(2);
	SCL_L;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
	u8 t;
	SDA_OUT();
	SCL_L; //拉低时钟开始数据传输
	for (t = 0; t < 8; t++)
	{
		if (txd & 0x80)
			SDA_H
		else
			SDA_L;
		txd <<= 1;
		IIC_Delay_us(2); //对TEA5767这三个延时都是必须的
		SCL_H;
		IIC_Delay_us(2);
		SCL_L;
		//IIC_Delay_us(2);
	}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i, receive = 0;
	SDA_IN(); //SDA设置为输入
	for (i = 0; i < 8; i++)
	{
		SCL_L;
		IIC_Delay_us(2);
		SCL_H;
		receive <<= 1;
		if (SDA_READ)
			receive++;
		IIC_Delay_us(1);
	}
	if (!ack)
		IIC_NAck(); //发送nACK
	else
		IIC_Ack(); //发送ACK
	return receive;
}
//IIC延时函数
void IIC_Delay_us(u16 us)
{
	{
		u16 i = 0;
		while (us--)
		{
			i = 6;
			while (i--)
				;
		}
	}
}

iic.h文件

#ifndef __IIC_H
#define __IIC_H
#include "stm32f4xx_conf.h"
/*
IIC_SCL  --PB2
IIC_SDA  --PB1
*/
//IO方向设置
#define SDA_IN()  {GPIOB->MODER&=~(3<<(1*2));GPIOB->MODER|=0<<1*2;}	//PB1输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(1*2));GPIOB->MODER|=1<<1*2;} //PB1输出模式
//IO操作函数	 
#define SCL_L    	{GPIOB->ODR&=0xFFFB;}  //SCL拉低(1011)B
#define SCL_H   	{GPIOB->ODR|=0x0004;}  //SCL拉高(0100)4
#define SDA_L			{GPIOB->ODR&=0xFFFD;}  //SDA拉低(1101)D
#define SDA_H			{GPIOB->ODR|=0x0002;}  //SDA拉高(0010)2
#define SDA_READ		(GPIOB->IDR&0x0002)	 //SDA读取

#define ACK			1
#define NACK		0

void IIC_Init(void);					  //初始化IIC的IO口	
void IIC_Start(void);							//发送IIC开始信号
void IIC_Stop(void);							//发送IIC停止信号
void IIC_Send_Byte(u8 byte);	  //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				  //IIC等待ACK信号
void IIC_Ack(void);						  //IIC发送ACK信号
void IIC_NAck(void);					  //IIC不发送ACK信号
void IIC_Delay_us(u16 us);		  //IIC delay
#endif

htu21d.c

/**
  ******************************************************************************
  * @file    htu21d.c 
  * @brief   HTU21D 温湿度模块驱动
  ******************************************************************************
	*/
#include <stdio.h>
#include "htu21d.h"
#include "iic.h"
#include "delay.h"
#include "usart.h"

SENSOR_DATA_t g_sensorData ={0,0,0,0,0};
static u32 timer = 0;
static u8 isTempOrHumi = 1;//Temp firth,humi second;
static u8 htu21_res=0;
/*
 * HTU21D模块初始化函数
 */
void HTU21D_Init(void){
	IIC_Start();
	IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
	IIC_Wait_Ack();
	IIC_Send_Byte(CMD_RESET_CH21D);
	IIC_Wait_Ack();
	IIC_Stop();
	Delay_ms(18);
	HTU21D_Temp_Trig();
	Delay_ms(60);
}

/*
 *
 */
u8 HTU21D_ReadSensor(void){
	
	if(HasElapsed(&timer, 500)){
		if(isTempOrHumi){
			htu21_res = HTU21D_Read_Temp(&g_sensorData.innerTemp);
			HTU21D_Humi_Trig();
			isTempOrHumi = 0;
		}else{
			htu21_res = HTU21D_Read_Humi(&g_sensorData.humi);
			HTU21D_Temp_Trig();
			isTempOrHumi = 1;
		}
	}
	return htu21_res;
}
/*
 * 读取计算温度函数
 */
u8 HTU21D_Read_Temp(float* temp){
	u32 data;
	IIC_Start();
	IIC_Send_Byte((HTU21D_IIC_ADDR<<1)+1);
	
	if(!IIC_Wait_Ack()){
		data = IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(NACK);
		IIC_Stop();
		
		data >>= 8;
		data &= 0xFFFC;
		*temp = (175.72*data)/65536 - 46.85;
		return 0;
	}
	//iic error
	return 1;
}
/*
 * 读取计算湿度函数
 */
u8 HTU21D_Read_Humi(float* humi){
	u32 data;
	IIC_Start();
	IIC_Send_Byte((HTU21D_IIC_ADDR<<1)+1);
	
	if(!IIC_Wait_Ack()){
		data = IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(NACK);
		IIC_Stop();
		
		data >>= 8;
		data &= 0xFFF0;
		*humi = (125.0*data)/65536 - 6;
		return 0;
	}
	//iic error
	return 1;
}
/*
 * 开始温度检测函数
 */
void HTU21D_Temp_Trig(){
		IIC_Start();
		IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
		IIC_Wait_Ack();
		IIC_Send_Byte(CMD_T_TRIG);
		IIC_Wait_Ack();
}
/*
 * 开始湿度检测函数
 */
void HTU21D_Humi_Trig(){
		IIC_Start();
		IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
		IIC_Wait_Ack();
		IIC_Send_Byte(CMD_RH_TRIG);
		IIC_Wait_Ack();
}

htu21d.h

#ifndef __HTU21D_H
#define __HTU21D_H
#include "stm32f4xx_conf.h"

typedef struct 
{
	float pressure;
	float depth;
	float innerTemp;
	float humi;
	float waterTemp;
}SENSOR_DATA_t;
extern SENSOR_DATA_t g_sensorData;

#define HTU21D_IIC_ADDR 				0x40			// the HTU21D 7 bits iic device addr
#define CMD_LOADER_DATA					0x81			//the HTU21D iic device addr to read data		

#define CMD_T_TRIG_HOSTMODEL			0xE3			//trigger of measure temperature command
#define CMD_RH_TRIG_HOSTMODEL			0xE5			//trigger of measure relative humidity command
#define CMD_T_TRIG						0xF3			//trigger of measure temperature command
#define CMD_RH_TRIG						0xF5			//trigger of measure relative humidity command
#define CMD_USER_WRITE					0xE6			//write user reg command
#define CMD_USER_READ					0xE7			//read user reg command
#define CMD_RESET_CH21D						0xFE			//HTU21D reset command

void HTU21D_Init(void);
u8 HTU21D_ReadSensor(void);
u8 HTU21D_Read_Temp(float* temp);
u8 HTU21D_Read_Humi(float* humi);
void HTU21D_Temp_Trig(void);
void HTU21D_Humi_Trig(void);
void HTU21D_Process(void);
#endif

main.c

void HTU21D_Process(void)
{
HTU21D_ReadSensor()	printf("temp:%.3f,humi:%.3f\r\n",g_sensorData.innerTemp,g_sensorData.humi);
	}
}
int main()
{
	while(1)
	{
		HTU21D_Process();
		delay_ms(100);
	}
}

版权声明:本文为CSDN博主「一颗老番茄」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43532636/article/details/122092234

一、引脚

器件引脚

二、代码

iic.c文件

#include "iic.h"

/* 初始化模拟IIC
 *
 */
void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIOA时钟

	//GPIOB1,B2初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;	  //普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	  //上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);			  //初始化

	SCL_H;
	SDA_H;
}

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT(); //sda线输出
	SDA_H;
	SCL_H;
	IIC_Delay_us(4);
	SDA_L; //START:when CLK is high,DATA change form high to low
	IIC_Delay_us(4);
	SCL_L; //钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT(); //sda线输出
	SCL_L;
	SDA_L; //STOP:when CLK is high DATA change form low to high
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(1);
	SDA_H; //发送I2C总线结束信号
	IIC_Delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime = 0;
	SDA_IN(); //SDA设置为输入
	SDA_H;
	IIC_Delay_us(1);
	SCL_H;
	IIC_Delay_us(1);
	while (SDA_READ)
	{
		ucErrTime++;
		if (ucErrTime > 250)
		{
			IIC_Stop();
			return 1;
		}
	}
	SCL_L;
	IIC_Delay_us(30);
	return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
	SCL_L;
	SDA_OUT();
	SDA_L;
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(2);
	SCL_L;
}
//不产生ACK应答
void IIC_NAck(void)
{
	SCL_L;
	SDA_OUT();
	SDA_H;
	IIC_Delay_us(2);
	SCL_H;
	IIC_Delay_us(2);
	SCL_L;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
	u8 t;
	SDA_OUT();
	SCL_L; //拉低时钟开始数据传输
	for (t = 0; t < 8; t++)
	{
		if (txd & 0x80)
			SDA_H
		else
			SDA_L;
		txd <<= 1;
		IIC_Delay_us(2); //对TEA5767这三个延时都是必须的
		SCL_H;
		IIC_Delay_us(2);
		SCL_L;
		//IIC_Delay_us(2);
	}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i, receive = 0;
	SDA_IN(); //SDA设置为输入
	for (i = 0; i < 8; i++)
	{
		SCL_L;
		IIC_Delay_us(2);
		SCL_H;
		receive <<= 1;
		if (SDA_READ)
			receive++;
		IIC_Delay_us(1);
	}
	if (!ack)
		IIC_NAck(); //发送nACK
	else
		IIC_Ack(); //发送ACK
	return receive;
}
//IIC延时函数
void IIC_Delay_us(u16 us)
{
	{
		u16 i = 0;
		while (us--)
		{
			i = 6;
			while (i--)
				;
		}
	}
}

iic.h文件

#ifndef __IIC_H
#define __IIC_H
#include "stm32f4xx_conf.h"
/*
IIC_SCL  --PB2
IIC_SDA  --PB1
*/
//IO方向设置
#define SDA_IN()  {GPIOB->MODER&=~(3<<(1*2));GPIOB->MODER|=0<<1*2;}	//PB1输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(1*2));GPIOB->MODER|=1<<1*2;} //PB1输出模式
//IO操作函数	 
#define SCL_L    	{GPIOB->ODR&=0xFFFB;}  //SCL拉低(1011)B
#define SCL_H   	{GPIOB->ODR|=0x0004;}  //SCL拉高(0100)4
#define SDA_L			{GPIOB->ODR&=0xFFFD;}  //SDA拉低(1101)D
#define SDA_H			{GPIOB->ODR|=0x0002;}  //SDA拉高(0010)2
#define SDA_READ		(GPIOB->IDR&0x0002)	 //SDA读取

#define ACK			1
#define NACK		0

void IIC_Init(void);					  //初始化IIC的IO口	
void IIC_Start(void);							//发送IIC开始信号
void IIC_Stop(void);							//发送IIC停止信号
void IIC_Send_Byte(u8 byte);	  //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				  //IIC等待ACK信号
void IIC_Ack(void);						  //IIC发送ACK信号
void IIC_NAck(void);					  //IIC不发送ACK信号
void IIC_Delay_us(u16 us);		  //IIC delay
#endif

htu21d.c

/**
  ******************************************************************************
  * @file    htu21d.c 
  * @brief   HTU21D 温湿度模块驱动
  ******************************************************************************
	*/
#include <stdio.h>
#include "htu21d.h"
#include "iic.h"
#include "delay.h"
#include "usart.h"

SENSOR_DATA_t g_sensorData ={0,0,0,0,0};
static u32 timer = 0;
static u8 isTempOrHumi = 1;//Temp firth,humi second;
static u8 htu21_res=0;
/*
 * HTU21D模块初始化函数
 */
void HTU21D_Init(void){
	IIC_Start();
	IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
	IIC_Wait_Ack();
	IIC_Send_Byte(CMD_RESET_CH21D);
	IIC_Wait_Ack();
	IIC_Stop();
	Delay_ms(18);
	HTU21D_Temp_Trig();
	Delay_ms(60);
}

/*
 *
 */
u8 HTU21D_ReadSensor(void){
	
	if(HasElapsed(&timer, 500)){
		if(isTempOrHumi){
			htu21_res = HTU21D_Read_Temp(&g_sensorData.innerTemp);
			HTU21D_Humi_Trig();
			isTempOrHumi = 0;
		}else{
			htu21_res = HTU21D_Read_Humi(&g_sensorData.humi);
			HTU21D_Temp_Trig();
			isTempOrHumi = 1;
		}
	}
	return htu21_res;
}
/*
 * 读取计算温度函数
 */
u8 HTU21D_Read_Temp(float* temp){
	u32 data;
	IIC_Start();
	IIC_Send_Byte((HTU21D_IIC_ADDR<<1)+1);
	
	if(!IIC_Wait_Ack()){
		data = IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(NACK);
		IIC_Stop();
		
		data >>= 8;
		data &= 0xFFFC;
		*temp = (175.72*data)/65536 - 46.85;
		return 0;
	}
	//iic error
	return 1;
}
/*
 * 读取计算湿度函数
 */
u8 HTU21D_Read_Humi(float* humi){
	u32 data;
	IIC_Start();
	IIC_Send_Byte((HTU21D_IIC_ADDR<<1)+1);
	
	if(!IIC_Wait_Ack()){
		data = IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(ACK);
		data <<= 8;
		data += IIC_Read_Byte(NACK);
		IIC_Stop();
		
		data >>= 8;
		data &= 0xFFF0;
		*humi = (125.0*data)/65536 - 6;
		return 0;
	}
	//iic error
	return 1;
}
/*
 * 开始温度检测函数
 */
void HTU21D_Temp_Trig(){
		IIC_Start();
		IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
		IIC_Wait_Ack();
		IIC_Send_Byte(CMD_T_TRIG);
		IIC_Wait_Ack();
}
/*
 * 开始湿度检测函数
 */
void HTU21D_Humi_Trig(){
		IIC_Start();
		IIC_Send_Byte(HTU21D_IIC_ADDR<<1);
		IIC_Wait_Ack();
		IIC_Send_Byte(CMD_RH_TRIG);
		IIC_Wait_Ack();
}

htu21d.h

#ifndef __HTU21D_H
#define __HTU21D_H
#include "stm32f4xx_conf.h"

typedef struct 
{
	float pressure;
	float depth;
	float innerTemp;
	float humi;
	float waterTemp;
}SENSOR_DATA_t;
extern SENSOR_DATA_t g_sensorData;

#define HTU21D_IIC_ADDR 				0x40			// the HTU21D 7 bits iic device addr
#define CMD_LOADER_DATA					0x81			//the HTU21D iic device addr to read data		

#define CMD_T_TRIG_HOSTMODEL			0xE3			//trigger of measure temperature command
#define CMD_RH_TRIG_HOSTMODEL			0xE5			//trigger of measure relative humidity command
#define CMD_T_TRIG						0xF3			//trigger of measure temperature command
#define CMD_RH_TRIG						0xF5			//trigger of measure relative humidity command
#define CMD_USER_WRITE					0xE6			//write user reg command
#define CMD_USER_READ					0xE7			//read user reg command
#define CMD_RESET_CH21D						0xFE			//HTU21D reset command

void HTU21D_Init(void);
u8 HTU21D_ReadSensor(void);
u8 HTU21D_Read_Temp(float* temp);
u8 HTU21D_Read_Humi(float* humi);
void HTU21D_Temp_Trig(void);
void HTU21D_Humi_Trig(void);
void HTU21D_Process(void);
#endif

main.c

void HTU21D_Process(void)
{
HTU21D_ReadSensor()	printf("temp:%.3f,humi:%.3f\r\n",g_sensorData.innerTemp,g_sensorData.humi);
	}
}
int main()
{
	while(1)
	{
		HTU21D_Process();
		delay_ms(100);
	}
}

版权声明:本文为CSDN博主「一颗老番茄」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43532636/article/details/122092234

生成海报
点赞 0

一颗老番茄

我还没有学会写个人说明!

暂无评论

相关推荐

基于STM32的高精度频率计设计

前言 本文记录了博主完成的一个课设作品(学分为3.5分),题目需要利用ARM做出一个高精度频率计。具体要求如下: 1)实现对10M以内数字信号频率的高精度测量&#xff0c

HAL库控制PS2手柄

吐槽一下 最近买了个ps2手柄,结果买家发的例程全都是好几年前的库函数版本,尝试移植基本没啥可能。虽然PS2手柄已经被开发很久了,不过我看网上用hal库来写控制的很少,例程也都是用库函数

STM32G4之RTC实时时钟

前言 一、RTC介绍 STM32 的 RTC 外设(Real Time Clock) ,实质是一个掉电后还继续运行的定时器。STM32G4 的 RTC,是一个独立的 BCD 定时器/计数器

stm32进不去串口中断的问题

今天遇到了特别棘手的问题,程序进入串口中断 原本应该进入这段程序: void USART1_IRQHandler(void) {if(USART_GetITStatus(USART1,USART_IT_RXNE)