4. 体温监测与报警

任务说明

本案例面向医疗嵌入式系统入门,目标为:使用高精度温度传感器(以MAX30205为例,其测温精度为±0.1°C,专用于人体体温测量)连续采集体温数据,当温度超过设定阈值(默认37.5°C)时,驱动蜂鸣器发声、LED闪烁,实现声光报警。系统通过I2C接口与传感器通信,并在本地串口输出实时温度与报警状态,便于验证。

硬件连接

MCU (STM32F103) I2C1: PB6(SCL)/PB7(SDA) UART1: PA9(TX)/PA10(RX) GPIO: PA0(BUZ)/PA1(LED) MAX30205 I2C地址: 0x48 VDD: 3.3V GND: GND 精度: ±0.1°C 蜂鸣器 (有源) LED (红色) SCL (PB6) SDA (PB7) PA0 PA1 VDD=3.3V, GND共地 PC串口终端 115200-8-N-1 显示温度与报警状态 UART TX (PA9)

软件实现

以下代码基于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采样一次
    }
}

编译与烧录

  1. 使用STM32CubeMX创建工程,使能I2C1(PB6/PB7)、USART1(PA9/PA10,115200波特率),并配置PA0、PA1为GPIO输出。
  2. 将上述代码复制到main.c对应位置,确保HAL库初始化顺序正确。
  3. 编译工程,通过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秒内触发;降温后报警自动恢复。满足以上条件即判定案例通过。