项目编号:STM32-T003

项目名称:基于STM32的实时健康监测系统

【开源链接】

通过网盘分享的文件:STM32-T003 基于STM32的实时健康监测系统

链接: https://pan.baidu.com/s/1_nTg1_RebU1kPMXupSG6Fw?pwd=5642 提取码: 5642 

【摘要】

        本项目设计了一套基于STM32F103C8T6单片机的实时健康监测系统,集成多种传感器与通信模块,具备数据采集、显示、上传与远程交互等功能。系统采用MAX30102传感器实时监测心率与血氧,DHT11模块获取环境温湿度信息,GPS模块提供位置信息,并通过OLED显示屏进行本地实时显示。利用ESP8266-01S模块实现Wi-Fi通信,系统可将各类监测数据上传至云平台,实现与手机APP及上位机(QT Python)软件的远程交互。用户可通过APP远程设定各项健康指标的阈值,当监测值超限时蜂鸣器自动报警,提升健康管理的主动性与安全性。该系统功能全面,信息交互灵活,适用于老年人健康看护、户外健康监测等应用场景,具有良好的扩展性与实用价值。

【所用硬件】

1、STM32F103C8T6最小系统板

2、OLED显示屏

3、MAX30102心率血氧传感器

4、DHT11温湿度模块

5、GPS模块

6、蜂鸣器模块

7、按键若干

8、ESP8266-01S WIFI模块

【系统框架图】

【软件流程图】

【核心代码展示】

#include "app_task.h"
#include "tim.h"

u8 str[50];
PAGE page;
POINT point;
u8 clear_flag;
PEOPLE people;
PEOPLE alarm;
u8 esp8266_send_flag;

TaskControlBlock TaskList[MAX_TASKS] = {0};
uint8_t RegisteredTasks = 0; // 已注册任务数
uint32_t SystemTick = 0;     // 系统时间基准

// 任务注册函数
int8_t Task_Register(uint8_t id, uint32_t interval, void (*task_func)(void *), void *param)
{
    if (RegisteredTasks >= MAX_TASKS)
        return -1;

    TaskList[RegisteredTasks].TaskID = id;
    TaskList[RegisteredTasks].PollingInterval = interval;
    TaskList[RegisteredTasks].TimerCounter = 0;
    TaskList[RegisteredTasks].RunFlag = 0;
    TaskList[RegisteredTasks].EnableFlag = 1;
    TaskList[RegisteredTasks].TaskHook = task_func;
    TaskList[RegisteredTasks].TaskParam = param;

    RegisteredTasks++;
    return 0;
}

// 任务使能控制
void Task_Enable(uint8_t id, uint8_t enable)
{
    for (int i = 0; i < RegisteredTasks; i++)
    {
        if (TaskList[i].TaskID == id)
        {
            TaskList[i].EnableFlag = enable;
            break;
        }
    }
}

void Led_Task(void *pt)
{
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}

void Beep_Task(void *pt)
{
    if(people.temp>alarm.temp || people.humi>alarm.humi || people.heart>alarm.heart || people.oxygen>alarm.oxygen)
    {
        HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET);
    }
    else
    {
        HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET);
    }
}

void Key_Task(void *pt)
{
    switch (KEY_Scan(0))
    {
        case KEY1_PRES:{
            if(page == HOME_PAGE_1){

            }
            else if(page == HOME_PAGE_2){
                page = HOME_PAGE_1;
                clear_flag=1;
            }

        }break;
        
        case KEY2_PRES:{
            if(page == HOME_PAGE_1){
                page = HOME_PAGE_2;
                clear_flag=1;
            }
            else if(page == HOME_PAGE_2){
                
            }


        }break;

        case KEY3_PRES:{



        }break;

        case KEY4_PRES:{


        }break;
    }
}

void Dht11_Task(void *pt)
{

    if (DHT11_READ_DATA())
    {
        people.temp = DHT11_data[2];
        people.humi = DHT11_data[0];
    }
}

void ESP8266_Task(void *pt)
{
		sprintf(str,"#%d#%d#%d#%d#%s#%s#%d#%d#%d#%d#",people.temp,people.humi,people.heart,people.oxygen,GPS_data[0],GPS_data[1],alarm.temp,alarm.humi,alarm.heart,alarm.oxygen);
        ESP8266_SendData(str);

}

void Max30102_Task(void *pt)
{
    MAX30102_GetData(&people.heart,&people.oxygen);
}

void GPS_Task(void *pt)
{
    parseGpsBuffer();
    GPS_Count(Save_Data.longitude,Save_Data.latitude);  //计算一次GPS坐标
}

void Ui_Task(void *pt)
{

    if (page == HOME_PAGE_1)
    {
        /*健康检测系统*/
        OLED_ShowChinese(16, 0, 0, 16, 1);
        OLED_ShowChinese(32, 0, 1, 16, 1);
        OLED_ShowChinese(48, 0, 2, 16, 1);
        OLED_ShowChinese(64, 0, 3, 16, 1);
        OLED_ShowChinese(80, 0, 4, 16, 1);
        OLED_ShowChinese(96, 0, 5, 16, 1);

        /*温度:*/
        OLED_ShowChinese(0, 16, 6, 16, 1);
        OLED_ShowChinese(16, 16, 8, 16, 1);
        OLED_ShowChinese(32, 16, 9, 16, 1);
        // OLED_ShowNum(48,16,people.temp,2,16,1);
        sprintf(str, "%dC", people.temp);
        OLED_ShowString(48, 16, str, 16, 1);

        /*湿度:*/
        OLED_ShowChinese(0, 32, 7, 16, 1);
        OLED_ShowChinese(16, 32, 8, 16, 1);
        OLED_ShowChinese(32, 32, 9, 16, 1);
        sprintf(str, "%d%%", people.humi);
        OLED_ShowString(48, 32, str, 16, 1);

        /*心率:*/
        OLED_ShowChinese(0, 48, 10, 16, 1);
        OLED_ShowChinese(16, 48, 11, 16, 1);
        OLED_ShowChinese(32, 48, 9, 16, 1);
        sprintf(str,"%3dBPM",people.heart);
        OLED_ShowString(48, 48, str, 16, 1);
    }
    else if (page == HOME_PAGE_2)
    {
        /*健康检测系统*/
        OLED_ShowChinese(16, 0, 0, 16, 1);
        OLED_ShowChinese(32, 0, 1, 16, 1);
        OLED_ShowChinese(48, 0, 2, 16, 1);
        OLED_ShowChinese(64, 0, 3, 16, 1);
        OLED_ShowChinese(80, 0, 4, 16, 1);
        OLED_ShowChinese(96, 0, 5, 16, 1);

        /*血氧:*/
        OLED_ShowChinese(0, 16, 12, 16, 1);
        OLED_ShowChinese(16, 16, 13, 16, 1);
        OLED_ShowChinese(32, 16, 9, 16, 1);
        sprintf(str,"%2d%%",people.oxygen);
        OLED_ShowString(48, 16, str, 16, 1);

        /*经度:*/
        OLED_ShowChinese(0, 32, 14, 16, 1);
        OLED_ShowChinese(16, 32, 15, 16, 1);
        OLED_ShowChinese(32, 32, 9, 16, 1);
        sprintf(str,"%s",GPS_data[0]);
        OLED_ShowString(48, 32, str, 16, 1);

        /*纬度:*/
        OLED_ShowChinese(0, 48, 16, 16, 1);
        OLED_ShowChinese(16, 48, 17, 16, 1);
        OLED_ShowChinese(32, 48, 9, 16, 1);
        sprintf(str,"%s",GPS_data[1]);
        OLED_ShowString(48, 48, str, 16, 1);

    }

    OLED_Refresh();
    if (clear_flag == 1)
    {
        clear_flag = 0;
        OLED_Clear();
    }
}

void Task_Init(void)
{
    Task_Register(1, 1000, Led_Task, NULL);
    Task_Register(2, 500, Beep_Task, NULL);
    Task_Register(3, 1000, Dht11_Task, NULL);
    Task_Register(4, 1000, ESP8266_Task, NULL);
    Task_Register(5, 100, Max30102_Task, NULL);
    Task_Register(6, 50, Ui_Task, NULL);
    Task_Register(7, 1, Key_Task, NULL);
    Task_Register(8, 3000, GPS_Task, NULL);

    //设置报警阈值
    alarm.heart = 130;
    alarm.oxygen = 99;
    alarm.temp = 25;
    alarm.humi = 70;
}

void Task_Run(void)
{
    for (int i = 0; i < RegisteredTasks; i++)
    {
        if (TaskList[i].RunFlag && TaskList[i].EnableFlag)
        {
            // 执行任务函数
            if (TaskList[i].TaskHook != NULL)
            {
                TaskList[i].TaskHook(TaskList[i].TaskParam);
            }
            // 清除运行标志
            TaskList[i].RunFlag = 0;
        }
    }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(htim);

    /* NOTE : This function should not be modified, when the callback is needed,
              the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
     */

    static u32 tick_time = 0;
    if (htim->Instance == TIM2)
    {
        tick_time++;
        // 遍历任务列表更新计数器
        for (int i = 0; i < RegisteredTasks; i++)
        {
            if (TaskList[i].EnableFlag)
            {
                TaskList[i].TimerCounter++;

                // 达到时间间隔时设置运行标志
                if (TaskList[i].TimerCounter >= TaskList[i].PollingInterval)
                {
                    TaskList[i].RunFlag = 1;
                    TaskList[i].TimerCounter = 0;
                }
            }
        }
    }
}

【原理图】

【硬件实物图】

【实物演示】

STM32-T003-实时健康监测系统

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐