4. 体温连续监测与异常报警

任务目标

在可穿戴设备上通过皮肤温度传感器(如Maxim MAX30205或TI TMP117)连续读取体温数据,当温度超过设定阈值(如38.0℃)时触发报警(LED点亮+蜂鸣器鸣响),并在串口输出报警信息。本案例使用STM32F103微控制器与I2C接口的TMP117传感器实现完整闭环。

硬件与依赖

  • 主控:STM32F103C8T6(Blue Pill),I2C1:PB6(SCL)、PB7(SDA)
  • 传感器:TMP117(I2C地址0x48),VCC接3.3V,GND接地
  • 报警输出:PA1接LED(串联220Ω电阻),PA2接蜂鸣器(NPN三极管驱动)
  • 软件:STM32CubeIDE或Keil MDK,使用标准外设库或HAL库均可

核心实现

以下代码实现完整的温度读取与报警逻辑。TMP117的寄存器0x00为温度结果寄存器,数据格式为16位有符号数,分辨率0.0078125℃/LSB。代码每500ms读取一次温度,连续3次超过阈值则触发报警并保持,直到温度回落至阈值以下0.5℃才解除。

// main.c 核心逻辑(使用HAL库)
#include "stm32f1xx_hal.h"

#define TMP117_ADDR     0x48 << 1
#define TMP117_TEMP_REG 0x00
#define ALARM_THRESHOLD 38.0f
#define HYSTERESIS      0.5f
#define SAMPLE_INTERVAL 500  // ms

I2C_HandleTypeDef hi2c1;
float current_temp = 0.0f;
uint8_t alarm_active = 0;
uint8_t over_count = 0;

// 读取TMP117温度(单位:℃)
float read_tmp117_temperature(void) {
    uint8_t reg = TMP117_TEMP_REG;
    uint8_t data[2] = {0};
    int16_t raw;
    float temp;

    HAL_I2C_Master_Transmit(&hi2c1, TMP117_ADDR, &reg, 1, 100);
    HAL_I2C_Master_Receive(&hi2c1, TMP117_ADDR, data, 2, 100);

    raw = (int16_t)((data[0] << 8) | data[1]);
    temp = raw * 0.0078125f;
    return temp;
}

// 报警控制
void set_alarm(uint8_t state) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, state ? GPIO_PIN_SET : GPIO_PIN_RESET);  // LED
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, state ? GPIO_PIN_SET : GPIO_PIN_RESET);  // 蜂鸣器
}

// 主循环中的温度监测与报警逻辑
void temperature_monitor_task(void) {
    current_temp = read_tmp117_temperature();

    if (!alarm_active) {
        if (current_temp >= ALARM_THRESHOLD) {
            over_count++;
            if (over_count >= 3) {  // 连续3次超阈值才报警,防抖动
                alarm_active = 1;
                set_alarm(1);
                printf("ALARM: Temp=%.2f°C exceeded %.1f°C\r\n", current_temp, ALARM_THRESHOLD);
            }
        } else {
            over_count = 0;
        }
    } else {
        // 报警状态下,温度回落至阈值-迟滞值以下才解除
        if (current_temp < (ALARM_THRESHOLD - HYSTERESIS)) {
            alarm_active = 0;
            over_count = 0;
            set_alarm(0);
            printf("ALARM CLEARED: Temp=%.2f°C\r\n", current_temp);
        }
    }
}

// 定时器回调(500ms周期)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM3) {
        temperature_monitor_task();
    }
}

int main(void) {
    HAL_Init();
    // ... 系统时钟配置(72MHz)、GPIO、I2C、TIM3初始化代码由CubeMX生成 ...

    // 启动500ms定时器
    HAL_TIM_Base_Start_IT(&htim3);

    while (1) {
        // 主循环可处理其他任务
    }
}

运行与验证

  1. 使用STM32CubeMX配置I2C1(100kHz)、PA1/PA2为推挽输出、TIM3定时500ms中断,生成初始化代码后,将上述逻辑加入工程。
  2. 编译烧录后,打开串口助手(115200-8-N-1),观察温度输出。
  3. 验证步骤:
  • 正常状态:用手触摸传感器使其升温至38℃以上并保持,观察LED与蜂鸣器应在约1.5秒(3次采样)内激活,串口打印ALARM信息。
  • 恢复状态:移开热源,待温度降至37.5℃以下,报警应自动解除,LED熄灭、蜂鸣器停止,串口打印ALARM CLEARED。
  • 判定通过条件:报警触发阈值与解除迟滞行为与代码设定一致,串口输出温度值与实际体温计误差不超过±0.3℃。

关键说明

  • 若使用MAX30205替代TMP117,需注意其I2C地址为0x90(8位),且温度寄存器为0x00,数据格式同为16位有符号,但分辨率不同(0.00390625℃/LSB),需相应调整转换系数。
  • 连续3次采样确认是为了避免瞬时干扰导致误报;迟滞回差防止报警在阈值附近频繁切换。
  • 实际穿戴场景中,皮肤温度通常低于核心体温,如需报警对应发热状态,阈值应根据佩戴位置校准(如腋下比体表高约0.5℃)。