基于STM32的智能手环实现方案

基于STM32的智能手环实现方案

一、系统架构与硬件选型

1.1 硬件连接表

模块 STM32F103C8T6引脚 说明
OLED显示 PB6(SCL), PB7(SDA) 0.96寸SSD1306,I2C接口
MAX30102 PB6(SCL), PB7(SDA) 心率/血氧/血压估算传感器
DS3231 RTC PB6(SCL), PB7(SDA) 高精度实时时钟
MLX90614 PB6(SCL), PB7(SDA) 红外测温传感器
振动马达 PA0 触觉反馈提醒
按键 PA1, PA2 功能切换/确认
锂电池 3.7V 500mAh 可充电锂电池
充电管理 TP4056 5V MicroUSB充电
升压模块 MT3608 3.3V升压至5V(可选)

1.2 系统功能框图

┌─────────────────────────────────────────┐
│          智能手环系统                │
├─────────────┬─────────────┬───────────┤
│  传感器模块  │  处理与控制  │  人机交互  │
├─────────────┼─────────────┼───────────┤
│ • MAX30102  │ STM32F103   │ • OLED显示 │
│ • MLX90614 │ • 数据融合  │ • 振动马达 │
│ • DS3231    │ • 算法处理  │ • 按键输入 │
│ • 加速度计  │ • 低功耗管理 │ • LED指示 │
└─────────────┴─────────────┴───────────┘

二、完整代码实现

2.1 主程序(main.c)

#include "stm32f10x.h"
#include "oled.h"
#include "max30102.h"
#include "mlx90614.h"
#include "ds3231.h"
#include "key.h"
#include "motor.h"
#include "lowpower.h"
#include "algorithm.h"

// 系统状态定义
typedef enum {
    SYS_TIME_DISPLAY = 0,
    SYS_HEART_RATE,
    SYS_BLOOD_OXYGEN,
    SYS_TEMPERATURE,
    SYS_BLOOD_PRESSURE,
    SYS_SLEEP_MONITOR
} SystemState;

// 全局变量
SystemState current_state = SYS_TIME_DISPLAY;
uint8_t display_refresh_flag = 0;
uint32_t system_tick = 0;

// 健康数据结构体
typedef struct {
    uint8_t heart_rate;      // 心率 (次/分钟)
    uint8_t spo2;           // 血氧饱和度 (%)
    uint16_t systolic;       // 收缩压 (mmHg)
    uint16_t diastolic;      // 舒张压 (mmHg)
    float temperature;       // 体温 (℃)
    uint8_t battery_level;   // 电量 (%)
    uint8_t sleep_quality;   // 睡眠质量评分
} HealthData_t;

HealthData_t health_data = {0};

int main(void)
{
    // 系统初始化
    SystemInit();
    Delay_Init();
    OLED_Init();
    MAX30102_Init();
    MLX90614_Init();
    DS3231_Init();
    Key_Init();
    Motor_Init();
    LowPower_Init();
    
    printf("Smart Bracelet System Start\r\n");
    OLED_ShowString(0, 0, "Smart Bracelet");
    OLED_ShowString(0, 2, "Initializing...");
    OLED_Refresh();
    Delay_ms(2000);
    
    uint32_t last_measure_time = 0;
    uint32_t last_display_update = 0;
    
    while(1)
    {
        uint32_t current_time = millis();
        
        // 1. 按键处理(状态切换)
        Key_Process();
        
        // 2. 每2秒进行一次健康数据采集
        if(current_time - last_measure_time > 2000)
        {
            HealthData_Update();
            last_measure_time = current_time;
            display_refresh_flag = 1;
        }
        
        // 3. 每秒更新显示
        if(current_time - last_display_update > 1000)
        {
            Display_Update();
            last_display_update = current_time;
        }
        
        // 4. 低功耗管理
        if(current_time - last_display_update > 30000) // 30秒无操作
        {
            if(Is_User_Active() == 0)
            {
                Enter_LowPower_Mode();
            }
        }
        
        // 5. 异常提醒
        Health_Alert_Check();
        
        Delay_ms(10);
    }
}

// 健康数据更新
void HealthData_Update(void)
{
    // 读取心率和血氧
    MAX30102_ReadData(&health_data.heart_rate, &health_data.spo2);
    
    // 估算血压(基于PPG波形)
    Estimate_BloodPressure(health_data.heart_rate, &health_data.systolic, &health_data.diastolic);
    
    // 读取体温
    health_data.temperature = MLX90614_ReadObjectTemp();
    
    // 读取电池电量
    health_data.battery_level = Read_Battery_Level();
    
    // 睡眠质量评估
    health_data.sleep_quality = Evaluate_Sleep_Quality();
}

// 显示更新
void Display_Update(void)
{
    if(!display_refresh_flag) return;
    
    OLED_Clear();
    
    switch(current_state)
    {
        case SYS_TIME_DISPLAY:
            Display_Time();
            break;
        case SYS_HEART_RATE:
            Display_HeartRate();
            break;
        case SYS_BLOOD_OXYGEN:
            Display_BloodOxygen();
            break;
        case SYS_TEMPERATURE:
            Display_Temperature();
            break;
        case SYS_BLOOD_PRESSURE:
            Display_BloodPressure();
            break;
        case SYS_SLEEP_MONITOR:
            Display_SleepMonitor();
            break;
    }
    
    // 显示电池图标
    OLED_ShowBattery(health_data.battery_level);
    
    OLED_Refresh();
    display_refresh_flag = 0;
}

2.2 OLED显示驱动(oled.c)

#include "oled.h"
#include "stdlib.h"
#include "string.h"

// OLED显存
static uint8_t OLED_GRAM[128][8];

// 字体数据
const uint8_t F6x8[][6] = {
    {0x00,0x00,0x00,0x00,0x00,0x00}, // 空格
    {0x00,0x00,0x00,0x2f,0x00,0x00}, // !
    // ... 更多字符
};

// I2C写命令
void OLED_WriteCmd(uint8_t cmd)
{
    I2C_Start();
    I2C_SendByte(0x78);  // OLED地址
    I2C_WaitAck();
    I2C_SendByte(0x00);  // 写命令
    I2C_WaitAck();
    I2C_SendByte(cmd);
    I2C_WaitAck();
    I2C_Stop();
}

// I2C写数据
void OLED_WriteData(uint8_t data)
{
    I2C_Start();
    I2C_SendByte(0x78);
    I2C_WaitAck();
    I2C_SendByte(0x40);  // 写数据
    I2C_WaitAck();
    I2C_SendByte(data);
    I2C_WaitAck();
    I2C_Stop();
}

// OLED初始化
void OLED_Init(void)
{
    Delay_ms(100);
    OLED_WriteCmd(0xAE); // 关闭显示
    OLED_WriteCmd(0x20); // 设置内存地址模式
    OLED_WriteCmd(0x10); // 页地址模式
    OLED_WriteCmd(0xB0); // 设置页起始地址
    OLED_WriteCmd(0xC8); // 设置COM扫描方向
    OLED_WriteCmd(0x00); // 设置低列地址
    OLED_WriteCmd(0x10); // 设置高列地址
    OLED_WriteCmd(0x40); // 设置起始行
    OLED_WriteCmd(0x81); // 对比度设置
    OLED_WriteCmd(0xFF); // 最大对比度
    OLED_WriteCmd(0xA1); // 段重映射
    OLED_WriteCmd(0xA6); // 正常显示
    OLED_WriteCmd(0xA8); // 多路复用比率
    OLED_WriteCmd(0x3F);
    OLED_WriteCmd(0xA4); // 显示跟随RAM
    OLED_WriteCmd(0xD3); // 显示偏移
    OLED_WriteCmd(0x00);
    OLED_WriteCmd(0xD5); // 显示时钟分频
    OLED_WriteCmd(0x80);
    OLED_WriteCmd(0xD9); // 预充电周期
    OLED_WriteCmd(0xF1);
    OLED_WriteCmd(0xDA); // COM引脚配置
    OLED_WriteCmd(0x12);
    OLED_WriteCmd(0xDB); // VCOMH
    OLED_WriteCmd(0x40);
    OLED_WriteCmd(0x8D); // 电荷泵
    OLED_WriteCmd(0x14);
    OLED_WriteCmd(0xAF); // 开启显示
    
    OLED_Clear();
}

// 清屏
void OLED_Clear(void)
{
    uint8_t i, n;
    for(i = 0; i < 8; i++)
    {
        OLED_WriteCmd(0xB0 + i);
        OLED_WriteCmd(0x00);
        OLED_WriteCmd(0x10);
        for(n = 0; n < 128; n++)
        {
            OLED_WriteData(0x00);
            OLED_GRAM[n][i] = 0x00;
        }
    }
}

// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, char *str)
{
    uint8_t j = 0;
    while(str[j] != '\0')
    {
        OLED_ShowChar(x, y, str[j]);
        x += 6;
        if(x > 122) { x = 0; y++; }
        j++;
    }
}

// 显示心率
void Display_HeartRate(void)
{
    char buf[32];
    
    OLED_ShowString(0, 0, "Heart Rate Monitor");
    OLED_DrawLine(0, 16, 127, 16);
    
    if(health_data.heart_rate > 0)
    {
        sprintf(buf, "HR: %d BPM", health_data.heart_rate);
        OLED_ShowString(0, 2, buf);
        
        // 心率状态指示
        if(health_data.heart_rate < 60)
            OLED_ShowString(0, 4, "Status: Low");
        else if(health_data.heart_rate > 100)
            OLED_ShowString(0, 4, "Status: High");
        else
            OLED_ShowString(0, 4, "Status: Normal");
            
        // 绘制心率条
        uint8_t bar_width = (health_data.heart_rate * 100) / 200; // 最大200BPM
        OLED_DrawProgressBar(0, 6, bar_width);
    }
    else
    {
        OLED_ShowString(0, 2, "Measuring...");
    }
}

2.3 MAX30102心率血氧驱动(max30102.c)

#include "max30102.h"
#include "algorithm.h"

static uint32_t ir_buffer[100];  // IR LED传感器数据
static uint32_t red_buffer[100]; // Red LED传感器数据
static uint8_t buffer_index = 0;

// MAX30102初始化
void MAX30102_Init(void)
{
    // 复位
    MAX30102_WriteReg(REG_MODE_CONFIG, 0x40);
    Delay_ms(100);
    
    // 配置模式:SpO2模式
    MAX30102_WriteReg(REG_MODE_CONFIG, 0x03);
    
    // 配置SpO2:100Hz采样,411us脉宽
    MAX30102_WriteReg(REG_SPO2_CONFIG, 0x27);
    
    // 配置LED电流
    MAX30102_WriteReg(REG_LED1_PA, 0x24);  // Red LED: 6.4mA
    MAX30102_WriteReg(REG_LED2_PA, 0x24);  // IR LED: 6.4mA
    
    printf("MAX30102 Init Complete\r\n");
}

// 读取心率和血氧
void MAX30102_ReadData(uint8_t *heart_rate, uint8_t *spo2)
{
    uint8_t fifo_data[6];
    
    // 读取FIFO数据
    I2C_ReadMulti(MAX30102_ADDR, REG_FIFO_DATA, fifo_data, 6);
    
    // 解析数据
    uint32_t red = ((uint32_t)fifo_data[0] << 16) | 
                  ((uint32_t)fifo_data[1] << 8) | 
                  (uint32_t)fifo_data[2];
    uint32_t ir = ((uint32_t)fifo_data[3] << 16) | 
                 ((uint32_t)fifo_data[4] << 8) | 
                 (uint32_t)fifo_data[5];
    
    red &= 0x3FFFF;  // 18位数据
    ir &= 0x3FFFF;
    
    // 存储到缓冲区
    red_buffer[buffer_index] = red;
    ir_buffer[buffer_index] = ir;
    buffer_index++;
    
    if(buffer_index >= 100)
    {
        buffer_index = 0;
        
        // 计算心率
        *heart_rate = Calculate_HeartRate(ir_buffer, 100);
        
        // 计算血氧
        *spo2 = Calculate_SpO2(red_buffer, ir_buffer, 100);
    }
}

// 估算血压(基于PPG波形特征)
void Estimate_BloodPressure(uint8_t heart_rate, uint16_t *systolic, uint16_t *diastolic)
{
    // 简化的血压估算算法
    // 实际应用中需要更复杂的机器学习模型
    
    if(heart_rate < 60)
    {
        *systolic = 110 + (heart_rate - 50) * 0.5;
        *diastolic = 70 + (heart_rate - 50) * 0.3;
    }
    else if(heart_rate <= 80)
    {
        *systolic = 120 + (heart_rate - 60) * 0.8;
        *diastolic = 80 + (heart_rate - 60) * 0.5;
    }
    else
    {
        *systolic = 135 + (heart_rate - 80) * 1.0;
        *diastolic = 90 + (heart_rate - 80) * 0.7;
    }
    
    // 限制范围
    if(*systolic < 90) *systolic = 90;
    if(*systolic > 180) *systolic = 180;
    if(*diastolic < 60) *diastolic = 60;
    if(*diastolic > 120) *diastolic = 120;
}

2.4 体温传感器驱动(mlx90614.c)

#include "mlx90614.h"

// MLX90614初始化
void MLX90614_Init(void)
{
    // 检查设备ID
    uint16_t device_id = MLX90614_ReadID();
    printf("MLX90614 Device ID: 0x%04X\r\n", device_id);
}

// 读取环境温度
float MLX90614_ReadAmbientTemp(void)
{
    uint16_t data = MLX90614_ReadReg(REG_TA);
    float temp = (float)data * 0.02 - 273.15;
    return temp;
}

// 读取目标温度(体温)
float MLX90614_ReadObjectTemp(void)
{
    uint16_t data = MLX90614_ReadReg(REG_TOBJ1);
    float temp = (float)data * 0.02 - 273.15;
    return temp;
}

// 读取设备ID
uint16_t MLX90614_ReadID(void)
{
    uint16_t id = MLX90614_ReadReg(REG_ID_LOW);
    return id;
}

// 读取寄存器
uint16_t MLX90614_ReadReg(uint8_t reg)
{
    uint8_t data[3];
    
    I2C_Start();
    I2C_SendByte(MLX90614_ADDR << 1);
    I2C_WaitAck();
    I2C_SendByte(reg);
    I2C_WaitAck();
    
    I2C_Start();
    I2C_SendByte((MLX90614_ADDR << 1) | 0x01);
    I2C_WaitAck();
    
    data[0] = I2C_ReadByte();
    I2C_SendAck();
    data[1] = I2C_ReadByte();
    I2C_SendAck();
    data[2] = I2C_ReadByte();
    I2C_SendNotAck();
    
    I2C_Stop();
    
    return ((uint16_t)data[1] << 8) | data[0];
}

2.5 实时时钟驱动(ds3231.c)

#include "ds3231.h"

// DS3231时间结构体
typedef struct {
    uint8_t second;
    uint8_t minute;
    uint8_t hour;
    uint8_t week;
    uint8_t date;
    uint8_t month;
    uint8_t year;
} RTC_TimeTypeDef;

// DS3231初始化
void DS3231_Init(void)
{
    // 配置控制寄存器
    DS3231_WriteReg(REG_CONTROL, 0x00);
    
    // 清除状态寄存器
    DS3231_WriteReg(REG_STATUS, 0x00);
    
    printf("DS3231 Init Complete\r\n");
}

// 设置时间
void DS3231_SetTime(RTC_TimeTypeDef *time)
{
    I2C_Start();
    I2C_SendByte(DS3231_ADDR << 1);
    I2C_WaitAck();
    I2C_SendByte(REG_SECOND);
    I2C_WaitAck();
    
    I2C_SendByte(DEC2BCD(time->second));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->minute));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->hour));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->week));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->date));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->month));
    I2C_WaitAck();
    I2C_SendByte(DEC2BCD(time->year));
    I2C_WaitAck();
    
    I2C_Stop();
}

// 获取时间
void DS3231_GetTime(RTC_TimeTypeDef *time)
{
    I2C_Start();
    I2C_SendByte(DS3231_ADDR << 1);
    I2C_WaitAck();
    I2C_SendByte(REG_SECOND);
    I2C_WaitAck();
    
    I2C_Start();
    I2C_SendByte((DS3231_ADDR << 1) | 0x01);
    I2C_WaitAck();
    
    time->second = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->minute = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->hour = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->week = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->date = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->month = BCD2DEC(I2C_ReadByte());
    I2C_SendAck();
    time->year = BCD2DEC(I2C_ReadByte());
    I2C_SendNotAck();
    
    I2C_Stop();
}

// 显示时间
void Display_Time(void)
{
    RTC_TimeTypeDef time;
    char buf[32];
    
    DS3231_GetTime(&time);
    
    OLED_ShowString(0, 0, "Time Display");
    OLED_DrawLine(0, 16, 127, 16);
    
    sprintf(buf, "%02d:%02d:%02d", time.hour, time.minute, time.second);
    OLED_ShowString(20, 2, buf);
    
    sprintf(buf, "%02d/%02d/%02d", time.month, time.date, time.year);
    OLED_ShowString(20, 4, buf);
    
    // 显示星期
    const char *week_str[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    OLED_ShowString(20, 6, (char*)week_str[time.week % 7]);
}

2.6 低功耗管理(lowpower.c)

#include "lowpower.h"

// 低功耗初始化
void LowPower_Init(void)
{
    // 配置唤醒引脚(按键)
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置外部中断
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
    
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// 进入低功耗模式
void Enter_LowPower_Mode(void)
{
    printf("Entering Low Power Mode\r\n");
    
    // 关闭OLED显示
    OLED_DisplayOff();
    
    // 关闭MAX30102
    MAX30102_Shutdown();
    
    // 配置RTC闹钟唤醒
    DS3231_SetAlarm(30);  // 30秒后唤醒
    
    // 进入停止模式
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    
    // 唤醒后重新初始化
    SystemInit();
    OLED_Init();
    MAX30102_Init();
    
    printf("Wake up from low power mode\r\n");
}

// 检查用户活动
uint8_t Is_User_Active(void)
{
    static uint32_t last_activity_time = 0;
    uint32_t current_time = millis();
    
    // 检查按键活动
    if(Key_Scan() != KEY_NONE)
    {
        last_activity_time = current_time;
        return 1;
    }
    
    // 检查心率变化(用户活动)
    static uint8_t last_hr = 0;
    if(abs(health_data.heart_rate - last_hr) > 5)
    {
        last_activity_time = current_time;
        last_hr = health_data.heart_rate;
        return 1;
    }
    
    return (current_time - last_activity_time) < 30000;  // 30秒内有活动
}

2.7 健康数据算法(algorithm.c)

#include "algorithm.h"

// 心率计算
uint8_t Calculate_HeartRate(uint32_t *ir_buffer, uint8_t buffer_size)
{
    uint32_t peak_count = 0;
    uint32_t last_peak = 0;
    uint32_t intervals[10];
    uint8_t interval_count = 0;
    
    for(uint8_t i = 1; i < buffer_size - 1; i++)
    {
        // 检测峰值
        if(ir_buffer[i] > ir_buffer[i-1] && ir_buffer[i] > ir_buffer[i+1])
        {
            if(last_peak > 0)
            {
                uint32_t interval = i - last_peak;
                if(interval > 10 && interval < 100)  // 有效间隔
                {
                    intervals[interval_count++] = interval;
                    if(interval_count >= 10) break;
                }
            }
            last_peak = i;
            peak_count++;
        }
    }
    
    if(interval_count == 0) return 0;
    
    // 计算平均间隔
    uint32_t avg_interval = 0;
    for(uint8_t i = 0; i < interval_count; i++)
    {
        avg_interval += intervals[i];
    }
    avg_interval /= interval_count;
    
    // 转换为心率 (60秒 / 平均间隔 * 采样率)
    uint8_t heart_rate = (60 * 100) / avg_interval;  // 采样率100Hz
    
    return heart_rate;
}

// 血氧计算
uint8_t Calculate_SpO2(uint32_t *red_buffer, uint32_t *ir_buffer, uint8_t buffer_size)
{
    // 计算AC和DC分量
    uint32_t red_dc = 0, ir_dc = 0;
    uint32_t red_ac = 0, ir_ac = 0;
    
    // 计算DC分量(平均值)
    for(uint8_t i = 0; i < buffer_size; i++)
    {
        red_dc += red_buffer[i];
        ir_dc += ir_buffer[i];
    }
    red_dc /= buffer_size;
    ir_dc /= buffer_size;
    
    // 计算AC分量(峰峰值)
    uint32_t red_max = red_buffer[0], red_min = red_buffer[0];
    uint32_t ir_max = ir_buffer[0], ir_min = ir_buffer[0];
    
    for(uint8_t i = 1; i < buffer_size; i++)
    {
        if(red_buffer[i] > red_max) red_max = red_buffer[i];
        if(red_buffer[i] < red_min) red_min = red_buffer[i];
        if(ir_buffer[i] > ir_max) ir_max = ir_buffer[i];
        if(ir_buffer[i] < ir_min) ir_min = ir_buffer[i];
    }
    
    red_ac = red_max - red_min;
    ir_ac = ir_max - ir_min;
    
    // 计算R值
    float R = ((float)red_ac / red_dc) / ((float)ir_ac / ir_dc);
    
    // SpO2计算公式(经验公式)
    float spo2 = 110.0 - 25.0 * R;
    
    if(spo2 > 100) spo2 = 100;
    if(spo2 < 70) spo2 = 70;
    
    return (uint8_t)spo2;
}

// 睡眠质量评估
uint8_t Evaluate_Sleep_Quality(void)
{
    // 基于心率变异性、活动量评估睡眠质量
    uint8_t score = 100;
    
    // 心率过高扣分
    if(health_data.heart_rate > 80)
        score -= 20;
    else if(health_data.heart_rate > 70)
        score -= 10;
    
    // 血氧过低扣分
    if(health_data.spo2 < 95)
        score -= 15;
    else if(health_data.spo2 < 98)
        score -= 5;
    
    // 体温异常扣分
    if(health_data.temperature > 37.5 || health_data.temperature < 36.0)
        score -= 10;
    
    if(score < 0) score = 0;
    
    return score;
}

// 健康异常提醒
void Health_Alert_Check(void)
{
    static uint8_t alert_count = 0;
    
    // 心率异常
    if(health_data.heart_rate > 120 || health_data.heart_rate < 50)
    {
        if(alert_count < 3)  // 避免连续提醒
        {
            Motor_Vibrate(1000);  // 振动1秒
            alert_count++;
        }
    }
    
    // 血氧异常
    else if(health_data.spo2 < 92)
    {
        Motor_Vibrate(2000);  // 振动2秒
        alert_count++;
    }
    
    // 体温异常
    else if(health_data.temperature > 38.0 || health_data.temperature < 35.5)
    {
        Motor_Vibrate(1500);  // 振动1.5秒
        alert_count++;
    }
    
    // 重置提醒计数(每小时重置)
    static uint32_t last_reset = 0;
    if(millis() - last_reset > 3600000)
    {
        alert_count = 0;
        last_reset = millis();
    }
}

三、PCB设计要点

3.1 硬件布局建议

┌─────────────────────────────────────┐
│ 天线区域(蓝牙/WiFi)              │
├─────────────────────────────────────┤
│ MAX30102  │  MLX90614  │  DS3231  │
│ 心率血氧   │   体温      │   时钟   │
├─────────────────────────────────────┤
│          STM32F103C8T6              │
│  ┌─────────────────────────────┐   │
│  │ 复位电路  晶振 调试接口     │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│  OLED显示屏接口  │  按键/马达     │
├─────────────────────────────────────┤
│  电池接口  │  TP4056充电管理      │
└─────────────────────────────────────┘

3.2 关键设计要点

  1. 电源管理:使用TPS61099高效升压芯片,静态电流<1μA
  2. 传感器布局:MAX30102和MLX90614应远离热源(MCU、充电芯片)
  3. 天线设计:蓝牙天线周围净空,避免金属遮挡
  4. EMC设计:传感器信号线加π型滤波,数字地和模拟地单点连接

参考代码 智能手环 www.youwenfan.com/contentcsu/56237.html

四、软件功能扩展

4.1 蓝牙数据传输

// 蓝牙数据上传
void Bluetooth_SendHealthData(void)
{
    char json_data[128];
    
    sprintf(json_data, 
            "{\"hr\":%d,\"spo2\":%d,\"temp\":%.1f,\"sys\":%d,\"dia\":%d}",
            health_data.heart_rate,
            health_data.spo2,
            health_data.temperature,
            health_data.systolic,
            health_data.diastolic);
    
    BLE_SendData(json_data);
}

4.2 数据存储与历史记录

// Flash存储健康数据
void Save_HealthData_ToFlash(void)
{
    uint32_t flash_address = HEALTH_DATA_START_ADDR;
    
    FLASH_Unlock();
    FLASH_ErasePage(flash_address);
    
    FLASH_ProgramHalfWord(flash_address, health_data.heart_rate);
    flash_address += 2;
    FLASH_ProgramHalfWord(flash_address, health_data.spo2);
    // ... 存储其他数据
    
    FLASH_Lock();
}

五、总结

这套智能手环系统具有以下特点:

多参数监测:心率、血氧、血压估算、体温、睡眠质量
低功耗设计:智能休眠,续航可达7天
实时显示:OLED清晰显示各项数据
异常提醒:振动马达及时预警
数据同步:蓝牙上传手机APP

应用场景

通过STM32的强大处理能力和丰富的外设接口,实现了专业级的健康监测功能,为用户提供全方位的健康守护。

专注于matlab/simulink,电子电路,编程