I2C实践开发 — STM32-I2C-HDC1080温湿度采集系统
目录
- I2C实践开发 --- STM32-I2C-HDC1080温湿度采集系统
- 1. 引言
- 2. 系统架构
- 2.1 硬件架构
- 2.2 软件架构
- 3. 代码分析
- 3.1 I2C驱动文件 (i2c.h 和 i2c.c)
- 3.2 HDC1080传感器驱动文件 (hdc1080.h 和 hdc1080.c)
- 4. 功能总结
- 【HDC1080传感器寄存器地址概览】
- 5、源码分享
- i2c.h
- i2c.c
- hdc1080.h
- hdc1080.c
1. 引言
本项目旨在通过STM32F1系列微控制器实现对HDC1080温湿度传感器的控制与数据采集。HDC1080是一种高精度、低功耗的温湿度传感器,支持I2C接口通信。通过本系统,用户能够实时读取环境的温湿度数据,适用于多种场景,如工业自动化、智能家居等。
2. 系统架构
2.1 硬件架构
• 主控芯片 :STM32F1系列微控制器(如STM32F103C8T6)
• 传感器模块 :HDC1080温湿度传感器
• 通信接口 :I2C总线(主设备)
2.2 软件架构
• I2C驱动层 :负责I2C总线的初始化和数据传输。
• 传感器驱动层 :实现对HDC1080传感器的控制与数据读取。
• 上层应用 :根据需求调用传感器驱动层接口,获取温湿度数据并处理。
3. 代码分析
3.1 I2C驱动文件 (i2c.h 和 i2c.c)
目标 :配置STM32F1系列微控制器的I2C外设,实现I2C通信功能。
主要功能 :
- IIC_Init函数 :
- 使能I2C1和相关GPIO外设时钟。
- 配置GPIOB的Pin6(SCL)和Pin7(SDA)为开漏输出模式。
- 初始化I2C1外设,配置时钟频率为100kHz,采用7位地址模式。
- I2C1_ReadData函数 :
- 生成I2C启动信号,开始通信。
- 发送器件地址和寄存器地址。
- 读取指定长度的数据并存储到缓冲区中。
- 在通信结束时发送停止信号。
特点 :
- 严格按照I2C协议流程进行数据传输。
- 加入适当延时,确保数据传输可靠性。
3.2 HDC1080传感器驱动文件 (hdc1080.h 和 hdc1080.c)
目标 :通过I2C接口读取HDC1080传感器的温湿度数据。
主要功能 :
- HDC1080_ReadTemperature函数 :
• 初始化I2C总线。
• 读取温度数据寄存器(地址:0x00)。
• 将读取到的16位数据转换为摄氏度。 - HDC1080_ReadHumidity函数 :
• 初始化I2C总线。
• 读取湿度数据寄存器(地址:0x01)。
• 将读取到的16位数据转换为百分比表示的湿度值。 - HDC1080_ReadDeviceID函数 :
• 初始化I2C总线。
• 读取制造商ID(地址:0xFE)和设备ID(地址:0xFF)。
特点 :
• 严格按照HDC1080数据手册进行数据格式转换。
• 提供温度和湿度的精确测量。
4. 功能总结
本系统通过I2C协议实现了对HDC1080温湿度传感器的控制与数据采集,具备以下功能:
- 初始化I2C总线,配置STM32F1系列微控制器。
- 读取传感器的温度和湿度数据,并进行必要的计算,转换为实际的物理量。
读取传感器的制造商ID和设备ID,用于设备验证。
【HDC1080传感器寄存器地址概览】
5、源码分享
i2c.h
//i2c.h
#ifndef __IIC_H
#define __IIC_H
#include "sys.h"
// IO方向设置
#define SDA_IN() {GPIOB->CRH &= 0XFFFF0FFF; GPIOB->CRH |= 8 << 12;} // PB7 输入
#define SDA_OUT() {GPIOB->CRH &= 0XFFFF0FFF; GPIOB->CRH |= 3 << 12;} // PB7 输出
// IO操作定义
#define IIC_SCL PBout(6) // SCL
#define IIC_SDA PBout(7) // SDA
#define READ_SDA PBin(7) // 读取 SDA
/* IIC 初始化函数 */
void IIC_Init(void);
/* IIC 读取器件内部数据函数 */
uint8_t I2C1_ReadData(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t length);
#endif
i2c.c
// i2c.c
#include "i2c.h"
#include "../delay/delay.h"
#include "stm32f10x_i2c.h"
/*********************************************************************************
* @ 函数名 :IIC_Init
* @ 功能说明:IIC初始化函数
* @ 参数 :无
* @ 返回值 :无
********************************************************************************/
void IIC_Init(void) {
/* 定义结构体变量 */
GPIO_InitTypeDef GPIO_Initstructure;
I2C_InitTypeDef I2C_Initstructure;
/* 使能 I2C1 外设时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 开启 I2C1 外设时钟
/* 使能 GPIOB 和 GPIOA 外设时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启 GPIOB 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启 GPIOA 外设时钟
/* GPIO 配置(用于 I2C 的 SCL 和 SDA 引脚)*/
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // 设置 Pin6 和 Pin7,Pin6 为 SCL,Pin7 为 SDA
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF_OD; // 配置为开漏模式(I2C 外设需要)
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度为 50MHz
GPIO_Init(GPIOB, &GPIO_Initstructure); // 初始化 GPIOB 引脚
/* I2C 配置 */
I2C_Initstructure.I2C_ClockSpeed = 100000; // 设置 I2C 时钟频率为 100kHz
I2C_Initstructure.I2C_Mode = I2C_Mode_I2C; // 设置 I2C 工作模式为 I2C 模式
I2C_Initstructure.I2C_DutyCycle = I2C_DutyCycle_2; // 设置 Tlow/Thigh 的比例为 2
I2C_Initstructure.I2C_OwnAddress1 = 0x00; // 设置 I2C 主设备地址(此处为默认值 0x00)
I2C_Initstructure.I2C_Ack = I2C_Ack_Enable; // 使能 ACK 响应
I2C_Initstructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 设置 7 位地址模式
// I2C_DeInit(I2C1); // 可选:先进行 I2C 外设复位
I2C_Init(I2C1, &I2C_Initstructure); // 初始化 I2C 外设
I2C_Cmd(I2C1, ENABLE); // 启用 I2C 外设
}
/*********************************************************************************
* @ 函数名 :I2C1_ReadData
* @ 功能说明:使用IIC读取器件寄存器地址中的数据(本工程中读取HDC中的数据)
* @ 参数 :
* DeviceAddr:设备器件的地址
* RegAddr :要读取的数据所在寄存器地址
* pBuffer :缓冲区
* length :长度
* @ 返回值 :无
********************************************************************************/
uint8_t I2C1_ReadData(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t length) {
uint16_t i;
uint8_t Address;
I2C_GenerateSTART(I2C1, ENABLE); // 生成启动信号,开始 I2C 通信
/* 等待直到 I2C 外设准备好 */
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* 配置 7 位设备地址,并选择接收方向 */
Address = DeviceAddr << 1; // 设备地址左移 1 位,准备设置为 7 位地址
Address |= 0x00; // 选择发送方向(0表示写,1表示读)
/* 发送设备地址(发送器模式)*/
I2C_Send7bitAddress(I2C1, Address, I2C_Direction_Transmitter);
delay_ms(10); // 延时确保数据传输
/* 等待 I2C 进入传输模式 */
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
/* 发送寄存器地址 */
I2C_SendData(I2C1, RegAddr);
delay_ms(10); // 延时确保数据传输
/* 等待寄存器地址发送完成 */
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
/* 重新生成启动信号,准备读取数据 */
I2C_GenerateSTART(I2C1, ENABLE);
delay_ms(100); // 延时确保启动信号有效
/* 等待 I2C 外设进入接收模式 */
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* 发送设备地址并选择接收方向 */
Address = (DeviceAddr << 1) | 0x01; // 设备地址右移 1 位,并选择接收模式
I2C_Send7bitAddress(I2C1, Address, I2C_Direction_Receiver);
delay_ms(10); // 延时确保数据传输
/* 等待 I2C 进入接收模式 */
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
/* 读取数据 */
for (i = 0; i < length; i++) {
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); // 等待字节接收
pBuffer[i] = I2C_ReceiveData(I2C1); // 读取接收到的数据
delay_ms(1); // 延时确保数据读取
}
/* 关闭 ACK 响应,结束数据接收 */
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE); // 生成停止信号,结束传输
return 0; // 返回 0 表示成功
}
hdc1080.h
// hdc1080.h
#ifndef __HDC1080_H
#define __HDC1080_H
#include "sys.h"
#include "i2c.h"
/* HDC1080 传感器的 I2C 地址和寄存器地址定义 */
#define HDC1080_I2C_ADDR 0x40 // HDC1080 传感器的 I2C 地址(7 位地址),值为 0x40。这个地址是 7 位的,最右边的位(1)用于选择读取(读)或写操作(写)。
#define Temperature 0x00 // 温度寄存器地址,0x00 是 HDC1080 用于存储温度数据的寄存器地址。
#define Humidity 0x01 // 湿度寄存器地址,0x01 是 HDC1080 用于存储湿度数据的寄存器地址。
#define Manufacturer_ID 0xFE // 制造商 ID 寄存器地址,0xFE 是用于读取 HDC1080 制造商 ID 的寄存器地址,返回值通常是 0x5449。
#define Device_ID 0xFF // 设备 ID 寄存器地址,0xFF 是用于读取 HDC1080 设备 ID 的寄存器地址,返回值通常是 0x1050。
/* 配置值和状态定义 */
#define Manufacturer_ID_value 0x5449 // HDC1080 的制造商 ID 值,值为 0x5449,通常表示该传感器的制造商标识。
#define Device_ID_value 0x1050 // HDC1080 的设备 ID 值,值为 0x1050,表示该设备的唯一标识符。
#define Config_heateroff 0x1000 // 配置寄存器设置为关闭加热器,值为 0x1000,表示关闭加热器。
// 当加热器关闭时,传感器工作在低功耗模式下,适用于温度和湿度的常规测量。
#define Config_heateron 0x3000 // 配置寄存器设置为打开加热器,值为 0x3000,表示打开加热器。
// 打开加热器时,传感器的温度和湿度测量范围会增大,但会增加功耗。
/* 读取HDC1080器件中的温度 */
float HDC1080_ReadTemperature(void);
/* 读取HDC1080器件中的湿度 */
uint16_t HDC1080_ReadHumidity(void);
/* 读取HDC1080器件中的ID */
void HDC1080_ReadDeviceID(uint8_t *pDeviceID);
#endif
hdc1080.c
// hdc1080.c
#include "hdc1080.h"
#include "../../SYSTEM/I2C/i2c.h"
#include "usart.h"
#include "delay.h"
#include "math.h"
/*********************************************************************************
* @ 函数名 :HDC1080_ReadTemperature
* @ 功能说明:读取HDC1080器件中的温度
* @ 参数 :无
* @ 返回值 :无
********************************************************************************/
float HDC1080_ReadTemperature(void) {
IIC_Init(); // 防止IIC状态不对,先初始化下IIC状态
delay_ms(50);
uint8_t tempData[2]; // 存储从传感器读取的温度数据,2字节
uint16_t temperature = 0; // 读取到的原始温度数据
float finalTemperature = 0; // 转换后的最终温度值
/* 通过 I2C 读取温度数据(HDC1080_I2C_ADDR 为设备地址,Temperature 为温度寄存器地址)*/
I2C1_ReadData(HDC1080_I2C_ADDR, Temperature, tempData, 2);
temperature = (tempData[0] << 8) | tempData[1]; // 合并读取的两个字节为一个 16 位的温度值
finalTemperature = (temperature / 65536.0f) * 165.0f - 40.0f; // 根据 HDC1080 的数据手册,将原始值转换为实际的温度(单位:摄氏度)
// 温度公式: (temperature / 65536) * 165 - 40
finalTemperature = ((int)(finalTemperature * 100000)) / 100000.0f; // 保证温度结果精度到小数点后五位
return finalTemperature; // 返回最终的温度值
}
/*********************************************************************************
* @ 函数名 :HDC1080_ReadHumidity
* @ 功能说明:读取HDC1080器件中的湿度
* @ 参数 :无
* @ 返回值 :无
********************************************************************************/
uint16_t HDC1080_ReadHumidity(void) {
IIC_Init(); // 防止IIC状态不对,先初始化下IIC状态
delay_ms(50);
uint8_t humiData[2]; // 存储从传感器读取的湿度数据,2字节
uint16_t humidity; // 转换后的湿度值
/* 通过 I2C 读取湿度数据(HDC1080_I2C_ADDR 为设备地址,Humidity 为湿度寄存器地址)*/
I2C1_ReadData(HDC1080_I2C_ADDR, Humidity, humiData, 2);
humidity = (humiData[0] << 8) | humiData[1]; // 合并读取的两个字节为一个 16 位的湿度值
humidity = (humidity * 100 / 65536); // 根据 HDC1080 的数据手册,将原始值转换为实际的湿度值(百分比)
return humidity; // 返回最终的湿度值
}
/*********************************************************************************
* @ 函数名 :HDC1080_ReadDeviceID
* @ 功能说明:读取HDC1080器件中的ID
* @ 参数 :无
* @ 返回值 :无
********************************************************************************/
void HDC1080_ReadDeviceID(uint8_t *pDeviceID) {
IIC_Init(); // 防止IIC状态不对,先初始化下IIC状态
delay_ms(50);
/* 通过 I2C 读取 HDC1080 设备的 ID(寄存器地址为 0xFE)*/
I2C1_ReadData(HDC1080_I2C_ADDR, 0xFE, pDeviceID, 2);
}