前言

随着科学技术的革新,智能化生活已经开始实现,更多的人们的目光聚焦在智能化产品上面,一方面是对自身健康的关注,另一方面是对便携轻松的生活的向往,智能手环就作为其中的一种代表性产物。其主要应用于运动显示比如显示行走及跑步的步数,距离,速度。同时可以实时健康监测比如心率,血氧,体温等。是一款突出个性与人性的智能化产物。


一、系统方案的设计1.1系统功能分析

本设计是由STM32F103C8T6最小系统电路,DS3231时钟模块,ADXL345计步模块,MAX30100血氧心率模块,DS18B20温度模块,MPU6050体位检测模块,1.44寸TFT彩色液晶屏显示模块组成的嵌入式智能手环系统。

(1)通过DS3231时钟模块实现日期显示的功能

(2)使用传感器ADXL345检测人步数

(3)通过MAX30100传感器实时检测血氧心率;

(4)通过传感器DS18B20进行温度测量。

(5)通过MPU6050体位检测卧床病人是否跌倒或可以通过此功能蜂鸣器警报呼叫。

(6)通过1.44寸TFT彩色液晶屏实时显示日期,步数,距离,心率,血氧,跌倒状态以及温度值。

1.2系统总体结构

二、硬件电路的搭建2.1STM32最小系统组成部分

2.2S硬件引脚连接

2.2S实物连接图

(1)STM32单片机实物图如下图所示。

(2)DS3231实物图


(3)ADXL345模块实物图如下图所示


(4) MAX30100实物图

(5)MPU6050实物图

(6)DS18B20温度传感器的实物图

(7)1.44寸TFT显示模块

整体系统实物图
手工焊接是一种常见的原始焊接方法。

三、软件设计

本设计采用轮询的操作方式,首先在系统中断中间隔不同的时间给相应的标志位置一,比如:计步每隔0.2s计步标志位置一,时钟每隔1s置一一次。然后在主循环中检测标志位,如果标志位置一。刷新相应的值。

3.1系统流程图


下面是更为详细的流程图

3.2主函数代码
#include "stm32f10x.h"
  • #include "delay.h"
  • #include "led.h"
  • #include "uart.h"
  • #include "stdio.h"
  • #include "ds18b20.h"
  • #include "Lcd_Driver.h"
  • #include "TFT_demo.h"
  • #include "GUI.h"
  • #include "key.h"
  • #include "mpu6050.h"
  • #include "inv_mpu.h"
  • #include "inv_mpu_dmp_motion_driver.h"
  • #include "math.h"
  • #include "MAX30100.h"
  • #include "MAX30100_Filters.h"
  • #include "MAX30100_PulseOximeter.h"
  • #include "MAX30100_SpO2Calculator.h"
  • #include "myiic.h"
  • #include "timer3.h"
  • #include "adxl345.h"
  • #include "myiic_2.h"
  • #include "DS3231.h"
  • u8 ReadAdxl345;        //定时读取adxl345数据
  • u8 ErrorNum=0;        //记录错误次数
  • u16 Normal_num=0;     //正常次数
  • u16 Error_num=0;     //倾斜次数
  • u16 BuShu=0;       //步数脉冲量
  • u16 step_num = 0;     //计数步数
  • float disJuLi = 0;    //显示距离       
  • signed short HeartRate_val=0; //心跳速率
  • u8 SPO2_val = 0;       //血氧浓度
  • u8 mpu_count = 0;
  • u8 STAP_FLAG = 0;
  • u8 mpu_flag = 0;          //人体跌倒检测标志位 标志位1、2任意一个异常 该标志位为1  【1:跌倒,0:正常】
  • _Bool mpu_1_flag = 0;        //人体跌倒检测标志位1 角度异常标志  【1:异常,0:正常】
  • _Bool mpu_2_flag = 0;        //人体跌倒检测标志位2 加速度异常标志 【1:异常,0:正常】
  • _Bool mpu_temp = 0;         //缓存
  • _Bool temp_flag = 0;     //温度获取标志
  • _Bool max_flag = 0;      //心率血氧获取标志
  • _Bool time_flag = 0;     //时间获取标志
  • _Bool MPU_flag = 0;      //开关 陀螺仪姿态获取分析标志
  • _Bool MAX_flag = 0;      //开关 心率血氧获取分析标志
  • _Bool ADXL_flag = 0;     //开关 计步获取分析标志
  • int SVM;           //人体加速度向量幅值SVM
  • int main(void)
  • {
  • float pitch,roll,yaw;  //欧拉角
  • short aacx,aacy,aacz;  //加速度传感器原始数据
  • u8 t = 0;
  • u16 z = 0;        //温度中间缓存值
  • u16 temp_BuShu;
  • SysTick_Config(SystemCoreClock/1000);
  • Delay_Ms(100);
  • Lcd_Init();    //屏幕初始化
  • UART1_Init();   //串口调试 波特率115200
  • DS18B20_Init();  //DS18B20温度模块初始化 PA4
  • Gpio_Init();   //蜂鸣器初始化      PA5
  • EXTI_KEY_Config();//按键初始化       PA6
  • MPU_Init();    //MPU6050初始化     -----SCLK接到“PB10”脚 SDIN接到“PB11”脚
  • DS3231_Init();  //时钟模块初始化     -----SCLK接到“PA3 ”脚 SDIN接到“PA2 ”脚
  • Delay_Ms(100);  //等待初始化稳定
  • //测试时钟代码
  • // DS3231_Set(20,5,28,21,36,0);
  • // while(1)
  • // {
  • //  Delay_Ms(2000);  //等待初始化稳定
  • //  get_show_time();
  • //  printf("%u-%u-%u\t",calendar.w_year+2000,calendar.w_month,calendar.w_date);
  • //  printf("%u:%u:%u\r\n",calendar.hour,calendar.min,calendar.sec);
  • // }
  • IIC_Init();    //血氧浓度模块IIC初始化  -----SCLK接到“PB8 ”脚 SDIN接到“PB9 ”脚
  • TIM3_Init();   //每1ms执行一次中断, RunTime 每1ms加 1
  • SPO2_Init();   //血氧心率配置
  • boot_Demo();   //启动界面
  • Delay_Ms(1000);  //等待初始化稳定
  • Init_ADXL345();  //Init_ADXL345初始化   -----SCLK接到“PB6 ”脚 SDIN接到“PB7”脚
  • if(Single_Read_ADXL345(0X00)==0xe5)
  •   {
  •     Delay_Ms(5);
  •   }
  •   else
  •   {
  •     Delay_Ms(3);
  •   }
  • while(mpu_dmp_init())//DMP初始化
  •   {
  •   //printf("MPU6050 Error");
  •    Delay_Ms(200);
  • }
  • main_Demo();   //主界面
  • STAP_FLAG = 1;
  • while(1)
  • {
  •   //====人体温度检测显示====
  •   if(temp_flag)
  •   {
  •    z = (ds18b20_read()& 0x07FF);
  •    temperature = z/16.0;
  •    temp_flag = 0;
  •    snprintf((char*)str, sizeof(str), " %2.1f ", temperature);
  •    Gui_DrawFont_GBK16(40,64,WHITE, BLACK,str);
  •   }
  •   //====心跳血氧获取====
  •   if(MAX_flag)
  •   {
  •    POupdate();    //更新FIFO数据 血氧数据 心率数据
  •    if(max_flag)
  •    {
  •     max_flag = 0;
  •     show_max30100(HeartRate_val,SPO2_val);
  •    }
  •   }
  •   //====计步程序====
  •   if((!MPU_flag) && (!MAX_flag))
  •   {
  •    if(ReadAdxl345 == 1)   //定时读取adxl345数据
  •    {
  •     ReadAdxl345= 0;
  •     ReadData_x();        //三轴检测函数
  •     if((temp_Y>450)||(temp_Y<-450)) //查看正常次数     
  •     {
  •      Normal_num++;  //正常次数++
  •     }
  •     else
  •     {
  •      Error_num++;//倾斜次数
  •     }
  •     if((Error_num!=0)&&(Normal_num!=0))//检测到步数
  •     {
  •      BuShu++;   //步数脉冲量++
  •      Error_num=0;    //清除一个周期检测
  •      Normal_num=0;
  •     }
  •     step_num = BuShu/2;  //显示步数
  •     disJuLi = step_num*0.45;//显示距离
  •    
  •     if(BuShu != temp_BuShu){
  •      snprintf((char*)str, sizeof(str), "%u", step_num);
  •      Gui_DrawFont_GBK16(48,16,WHITE, BLACK,str);
  •      snprintf((char*)str, sizeof(str), "%0.1f", disJuLi);
  •      Gui_DrawFont_GBK16(48,96,WHITE, BLACK,str);
  •      temp_BuShu = BuShu;
  •     }
  •    }
  •   }       
  •   //获取时间
  •   if(time_flag)
  •   {
  •    time_flag = 0;
  •    get_show_time();
  •    sprintf((char*)str,"%u:%u:%u\r\n",calendar.hour,calendar.min,calendar.sec);
  •    Gui_DrawFont_GBK16(48,112,WHITE, BLACK,str);
  •    printf("%u-%u-%u\t",calendar.w_year+2000,calendar.w_month,calendar.w_date);
  •    printf("%u:%u:%u\r\n",calendar.hour,calendar.min,calendar.sec);
  •   }
  •   //====MPU6050数据获取====
  •   if(MPU_flag)
  •   {
  •    t++;
  •    if(t>=10)
  •    {
  •     t=0;
  •     if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
  •     {
  •      MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据  
  •      SVM = sqrt(pow(aacx,2)+  pow(aacy,2) + pow(aacz,2));
  •      //printf("pitch:%0.1f   roll:%0.1f   yaw:%0.1f   SVM:%u\r\n",fabs(pitch),fabs(roll),fabs(yaw),SVM);
  •      
  •      //分析x、y、z角度的异常判断
  •      if( fabs(pitch)>40 || fabs(roll)>40 || fabs(yaw)>40 )//倾斜角度的 【绝对值】 大于40°SVM大于设定的阈值时,即认为摔倒
  •       mpu_1_flag = 1;
  •      else
  •       mpu_1_flag = 0;
  •      //分析加速度SVM的异常判断
  •      if( SVM>23000 || SVM<12000 )
  •       mpu_2_flag = 1;
  •      else
  •       mpu_2_flag = 0;
  •      //综合欧拉角、SVM异常判断异常
  •      if( mpu_2_flag || mpu_1_flag )
  •      {
  •       mpu_flag = 1;
  •       show_mpu(1);
  •      }  
  •     }
  •    }
  •   }
  •   
  •   Delay_Ms(10);
  • }
  • }
  • void SysTick_Handler(void)
  • {
  • TimingDelay--;
  • if(STAP_FLAG)
  • {
  •   led_count++;
  •   if(led_count%200 == 0)
  •   {
  •    ReadAdxl345 = 1;
  •   }
  •   if(led_count == 1000)
  •   {
  •    led_count = 0;
  •    temp_flag = 1;
  •    max_flag = 1;
  •    time_flag = 1;
  •    if(mpu_flag)    //蜂鸣器响一秒
  •    {
  •     mpu_count++;
  •     if(mpu_count == 1)BEEP_ON;
  •     else if(mpu_count == 2)BEEP_OFF;
  •    }
  •    if(mpu_count == 3) //异常3秒回复状态
  •    {
  •     mpu_count = 0;
  •     mpu_flag = 0;
  •     show_mpu(0);
  •    }
  •    
  •   }
  • }
  • }
  • 复制代码

    代码结构如图

    四、系统测试

    五、总结

    想要实现更多的研究,就要深入的理解它,如果我们可以在智能手环中,我们可以引入操作系统,使用一些可以跑操作系统(Android)的处理器,可以让多功能的实现不是那么的有难度。