找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6543|回复: 4
收起左侧

基于STM32F103的心率传感器源代码

[复制链接]
ID:301268 发表于 2019-5-10 18:26 | 显示全部楼层 |阅读模式
基于STM32F103的心率传感器相关程序

单片机源程序如下:
  1. #include "led.h"
  2. #include "lcd.h"
  3. #include "key.h"
  4. #include "adc.h"         
  5. #include "timer.h"
  6. #include "common.h"
  7. #include "timer.h"
  8. #include "led.h"
  9. #include "beep.h"


  10. u8 q,i=0;
  11. u8 ave[50]={0};
  12. float ave_heart_rate=0;
  13. u8 sum(u8 m)
  14. {
  15.         ave[2]=ave[1];
  16.         ave[1]=ave[0];
  17.         ave[0]=m;
  18.         return ave[0]+ave[1]+ave[2];
  19. }
  20. //****************************************************************************
  21. //* 名    称: u8 8Average(u8 ch,u8 times)
  22. //* 功    能:取times次,然后平均
  23. //* 入口参数:ch: 采集每次i的值
  24. //*           times:获取次数
  25. //* 返回参数:通道ch的times次转换结果平均值
  26. //* 说    明:      
  27. //****************************************************************************/
  28. u16 Average(u8 ch,u8 times)
  29. {
  30.         if(ave[2] == 0)
  31.         {
  32.                 if (ave[1] == 0)
  33.                 {return ch/1;}
  34.                 else
  35.                 {return ch/2;}
  36.         }
  37.                 return ch/3;
  38. }          
  39. /****************************************************************************
  40. * 名    称: TIM2_Init(u16 auto_data,u16 fractional)
  41. * 功    能:定时器2初始化
  42. * 入口参数:auto_data: 自动重装值
  43. *           fractional: 时钟预分频数
  44. * 返回参数:无
  45. * 说    明:定时器溢出时间计算方法:Tout=((auto_data+1)*(fractional+1))/Ft(us)  Ft定时器时钟     
  46. ****************************************************************************/
  47. void TIM2_Init(u16 auto_data,u16 fractional)
  48. {
  49.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  50.         NVIC_InitTypeDef NVIC_InitStructure;

  51.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
  52.        
  53.         //定时器TIM2初始化
  54.         TIM_TimeBaseStructure.TIM_Period = auto_data; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值       
  55.         TIM_TimeBaseStructure.TIM_Prescaler = fractional; //设置用来作为TIMx时钟频率除数的预分频值
  56.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  57.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  58.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

  59.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM2中断,允许更新中断

  60.         //中断优先级NVIC设置
  61.         NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
  62.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
  63.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  64.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  65.         NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

  66.         TIM_Cmd(TIM2, ENABLE);  //使能TIMx                                         
  67. }
  68. //定时器2中断服务程序
  69. void TIM2_IRQHandler(void)   //TIM2中断
  70. {
  71.         if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
  72.                 {               
  73.                         q++;                  //没经过1s,记一次数
  74.                         while(q == 60)        //每一分钟重复一次
  75.                   {
  76.                                 LCD_DisplayNum(120,80,i*2/3,3,16,0);
  77.                         //BEEP=!BEEP;
  78.                                 ave_heart_rate=Average(sum(i*2/3),3);       //取3次心率的平均值

  79.                                 LCD_DisplayNum(150,110,ave_heart_rate,3,16,0);
  80.                                 LED1=!LED1;
  81.                                 q=0;
  82.                                 i=0;
  83.                         }
  84.                 }
  85.                 TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );    //清除TIMx更新中断标志
  86. }

  87. int main(void)
  88. {
  89.         u8 w=0,k=0;
  90.         int n=0,x=0;
  91.         float mov=0;
  92.         float qua;
  93.         u16 adc_data;
  94.         float temp;
  95.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  96.         delay_init();       //初始化延时函数
  97.         LED_Init();                                        //初始化LED
  98.         LCD_Init();         //初始化LCD接口
  99.         TIM2_Init(10000,7199); //定时器2时钟72M,分频系数7200,72M/7200=10K 所以计数10000次为1000ms,函数内部定时1min
  100.         ADC1_Init();        //初始化ADC
  101.         KEY_Init();       //按键初始化
  102.         LCD_Display_Dir(1);   //横屏

  103.         while(1)
  104.         {
  105.                
  106.                 if(n==0)
  107.                 {
  108.                         BRUSH_COLOR=BLUE;//设置字体为蓝色
  109.                         LCD_DisplayString(30,20,16,"heart_rate_VOL:");             
  110.                         //LCD_DisplayString(30,150,16,"ADC1_CH1_VOL:0.000V");         
  111.                         LCD_DisplayString(45,50,16,".");                       //先在固定位置显示小数点  
  112.                         LCD_DisplayString(30,80,16,"heart_rate:");
  113.                         LCD_DisplayString(30,110,16,"AVE.heart rate:");
  114.                        
  115.                         adc_data=Get_Adc_Average(ADC_Channel_1,10);//获取通道1的转换值,10次取平均
  116.                         temp=(float)adc_data*(3.3/4096);            //获取计算后的带小数的实际电压值,比如5.1141
  117.                         if(temp>=1.7)
  118.                         {        i++;
  119.                         }
  120.                         adc_data=temp;                              //赋值整数部分给adc_data变量,因为adc_data为u16整形
  121.                         LCD_DisplayNum(35,50,adc_data,1,16,0);    //显示电压值的整数部分,5.1141的话,这里就是显示5
  122.                         temp-=adc_data;                             //把已经显示的整数部分去掉,留下小数部分,比如5.1141-5=0.1141
  123.                         temp*=1000;                                 //小数部分乘以1000,例如:0.1141就转换为114.1,相当于保留三位小数。
  124.                         LCD_DisplayNum(55,50,temp,3,16,0X80);     //显示小数部分(前面转换为了整形显示),这里显示的就是114.
  125.                         delay_ms(50);       
  126.                         key_scan(0);       
  127. //                        if(keydown_data==KEY0_DATA)   //key0按下后马上执行相应代码
  128. //                        {
  129. //                                w++;
  130. //                                LCD_DisplayString(30,150,16,"Movement:");        //移动次数输入个位
  131. //                                mov=10*k+w;
  132. //                                LCD_DisplayNum(110,150,mov,4,16,0);
  133. //                        }
  134. //                        if(keydown_data==KEY1_DATA)     //key1按下后马上执行相应代码
  135. //                        {
  136. //                                k++;
  137. //                                LCD_DisplayString(30,150,16,"Movement:");        //移动次数输入十位
  138. //                                mov=10*k+w;
  139. //                                LCD_DisplayNum(110,150,mov,4,16,0);
  140. //                        }
  141.                         if(keydown_data==KEY2_DATA)  
  142.                         {
  143.                                 LCD_DisplayString(30,200,16,"Sleep Quality:     %");
  144.                                 if(ave_heart_rate<=150&&ave_heart_rate>=50)        //心率在50~150之间时
  145.                                 qua=(float)(((1-mov/140)/2+(-0.006*ave_heart_rate+1.1)/2)*100);
  146.                                 if(ave_heart_rate>150)                          //心率大于150
  147.                                         qua=(float)(((1-mov/140)/2+(0.2)/2)*100);
  148.                                 LCD_DisplayNum(150,200,qua,4,16,0);
  149.                         }
  150.                                 delay_ms(50);
  151.                                 if(keydown_data==KEY3_DATA)
  152.                         {
  153.                                 n++;
  154.                         }
  155.                 }
  156.                 if(n==1)
  157.                 {
  158.                         LCD_Clear(WHITE);//清屏
  159.                         n++;
  160.                 }
  161.                 if(n==2)
  162.                 {
  163.                 adc_data=Get_Adc_Average(ADC_Channel_1,10);
  164.                         //获取通道1的转换值,10次取平均
  165.                 temp=50*(float)adc_data*(3.3/4096);           
  166.                         //获取计算后的带小数的实际电压值,比如5.1141
  167.                 LCD_Color_DrawPoint(x,temp,RED);
  168.                 x++;
  169.                         if(x==320)
  170.                         {
  171.                                 LCD_Clear(WHITE);//清屏
  172.                                 x=0;
  173.                         }
  174.                 }
  175.         }
  176. }
复制代码

所有资料51hei提供下载:
程序.7z (530.45 KB, 下载次数: 190)
回复

使用道具 举报

ID:644582 发表于 2019-11-18 22:26 | 显示全部楼层
求分享
回复

使用道具 举报

ID:248814 发表于 2019-11-14 16:43 | 显示全部楼层
好东西,学习了
回复

使用道具 举报

ID:189285 发表于 2019-5-11 11:24 | 显示全部楼层
这个东西好
回复

使用道具 举报

ID:1 发表于 2019-5-11 03:56 | 显示全部楼层
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表