4. 体温监测与报警
任务说明
本案例面向医疗嵌入式系统入门,目标为:使用高精度温度传感器(以MAX30205为例,其测温精度为±0.1°C,专用于人体体温测量)连续采集体温数据,当温度超过设定阈值(默认37.5°C)时,驱动蜂鸣器发声、LED闪烁,实现声光报警。系统通过I2C接口与传感器通信,并在本地串口输出实时温度与报警状态,便于验证。
硬件连接
软件实现
以下代码基于STM32 HAL库,实现I2C读取MAX30205温度寄存器、阈值比较、声光报警控制及串口日志输出。代码结构清晰,可直接移植至标准HAL工程。
// main.c 核心逻辑(节选)
#include "main.h"
// MAX30205寄存器地址
#define MAX30205_ADDR (0x48 << 1) // 8位写地址
#define REG_TEMP 0x00 // 温度寄存器(16位)
#define REG_CONFIG 0x01 // 配置寄存器
#define REG_THYST 0x02 // 滞回阈值
#define REG_TOS 0x03 // 过温阈值
// 报警阈值:37.5°C,MAX30205数据格式为11位有符号,分辨率0.00390625°C
#define TEMP_ALARM_THRESH 9600 // 37.5 / 0.00390625 = 9600
// 外设句柄(由CubeMX生成)
extern I2C_HandleTypeDef hi2c1;
extern UART_HandleTypeDef huart1;
// 报警引脚定义
#define BUZZER_PIN GPIO_PIN_0 // PA0
#define LED_PIN GPIO_PIN_1 // PA1
#define GPIO_PORT GPIOA
// 读取温度并返回摄氏度(放大100倍,避免浮点)
int16_t Read_Temperature(void)
{
uint8_t buf[2];
int16_t raw;
int32_t temp_x100;
// 读取温度寄存器(16位,高字节在前)
HAL_I2C_Mem_Read(&hi2c1, MAX30205_ADDR, REG_TEMP, 1, buf, 2, 100);
raw = (int16_t)((buf[0] << 8) | buf[1]);
raw >>= 3; // 右移3位,得到11位有效数据
// 符号扩展(11位有符号数)
if (raw & 0x400) {
raw |= 0xF800;
}
// 转换为摄氏度×100: raw × 0.00390625 × 100 = raw × 0.390625
temp_x100 = (int32_t)raw * 390625 / 1000000;
return (int16_t)temp_x100;
}
// 报警控制
void Alarm_Control(uint8_t enable)
{
if (enable) {
HAL_GPIO_WritePin(GPIO_PORT, BUZZER_PIN, GPIO_PIN_SET); // 蜂鸣器响
HAL_GPIO_WritePin(GPIO_PORT, LED_PIN, GPIO_PIN_SET); // LED亮
} else {
HAL_GPIO_WritePin(GPIO_PORT, BUZZER_PIN, GPIO_PIN_RESET); // 蜂鸣器关
HAL_GPIO_WritePin(GPIO_PORT, LED_PIN, GPIO_PIN_RESET); // LED灭
}
}
// 主循环(节选)
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_UART1_Init();
// 初始化报警引脚为推挽输出
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = BUZZER_PIN | LED_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct);
// 配置MAX30205:比较模式,过温输出
uint8_t config = 0x02; // 比较模式,默认极性
HAL_I2C_Mem_Write(&hi2c1, MAX30205_ADDR, REG_CONFIG, 1, &config, 1, 100);
// 设置过温阈值37.5°C(写入11位数据,左移3位)
uint8_t tos_buf[2];
uint16_t tos_val = (TEMP_ALARM_THRESH & 0x07FF) << 3;
tos_buf[0] = (tos_val >> 8) & 0xFF;
tos_buf[1] = tos_val & 0xFF;
HAL_I2C_Mem_Write(&hi2c1, MAX30205_ADDR, REG_TOS, 1, tos_buf, 2, 100);
// 设置滞回阈值36.5°C(避免频繁抖动)
uint8_t thyst_buf[2];
uint16_t thyst_val = (int16_t)(36.5 / 0.00390625) & 0x07FF;
thyst_val <<= 3;
thyst_buf[0] = (thyst_val >> 8) & 0xFF;
thyst_buf[1] = thyst_val & 0xFF;
HAL_I2C_Mem_Write(&hi2c1, MAX30205_ADDR, REG_THYST, 1, thyst_buf, 2, 100);
char msg[64];
int16_t temp;
while (1)
{
temp = Read_Temperature();
int16_t temp_int = temp / 100;
int16_t temp_frac = temp % 100;
if (temp_frac < 0) temp_frac = -temp_frac;
// 串口输出温度值
int len = sprintf(msg, "Temp: %d.%02d C\r\n", temp_int, temp_frac);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, len, 100);
// 阈值判断:温度 ≥ 37.5°C 触发报警
if (temp >= 3750) {
Alarm_Control(1);
HAL_UART_Transmit(&huart1, (uint8_t*)"ALARM: OVER TEMP!\r\n", 20, 100);
} else {
Alarm_Control(0);
}
HAL_Delay(500); // 每500ms采样一次
}
}
编译与烧录
- 使用STM32CubeMX创建工程,使能I2C1(PB6/PB7)、USART1(PA9/PA10,115200波特率),并配置PA0、PA1为GPIO输出。
- 将上述代码复制到main.c对应位置,确保HAL库初始化顺序正确。
- 编译工程,通过ST-Link或串口ISP将生成的hex文件烧录至STM32F103开发板。
验证方法
测试准备:将MAX30205传感器紧贴人体腋下或使用恒温水浴模拟体温;打开PC串口终端(115200-8-N-1)。
操作与判定:
- 正常体温:当传感器温度低于37.5°C时,串口持续输出如
Temp: 36.87 C,蜂鸣器不响、LED不亮。 - 超温报警:用手紧握传感器或置于37.5°C以上热水中,串口输出
Temp: 37.62 C后出现ALARM: OVER TEMP!,同时蜂鸣器发声、LED点亮。 - 恢复:温度降至36.5°C以下(滞回区间),报警自动解除,蜂鸣器停止、LED熄灭。
判定标准:串口温度读数与标准水银体温计误差≤0.2°C;超温时声光报警在1秒内触发;降温后报警自动恢复。满足以上条件即判定案例通过。