找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1497|回复: 1
打印 上一主题 下一主题
收起左侧

arm心率计源代码

[复制链接]
跳转到指定楼层
楼主
ID:504670 发表于 2019-4-4 11:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
心率计可以将连接到板子上的心率传感器数据采集下来并使用算法计算心率值,并通过串口传输到指定的终端设备。可以直接接USB-TLL模块传输到PC端或者通过蓝牙模块传输到手机端。

单片机源程序如下:
  1.    //******************************说明********************************/



  2. #include "stdio.h"
  3. #include "common.h"
  4. #include "heartRateProcess.h"
  5. #define false 0
  6. #define true 1
  7. #define FOSC 11059200L                //系统时钟
  8. #define BAUD 115200                                //波特率
  9. #define T0MS (65536-FOSC/12/500)                //500HZ in 12T MODE
  10. #define         BUFFER_SIZE 10

  11. #define ADC_POWER 0x80                        //ADC POWER CONTROL BIT
  12. #define ADC_FLAG 0x10                        //ADC COMPLETE FLAG
  13. #define ADC_START 0x08;                        //ADC START CONTROL BIT
  14. #define ADC_SPEEDLL 0x00                //540 CLOCKS
  15. #define ADC_SPEEDL 0x20                        //360 CLOCKS
  16. #define ADC_SPEEDH 0x40                        //180 CLOCKS
  17. #define ADC_SPEEDHH 0x60                //90 CLOCKS
  18. #define ADC_MASK 0x01

  19. #define BLUE_SHIFT (1U << 5)
  20. #define BLUE_ON (GPIOD_PCOR = BLUE_SHIFT)
  21. #define BLUE_OFF (GPIOD_PSOR = BLUE_SHIFT)
  22. #define BLUE_TOGGLE (GPIOD_PTOR = BLUE_SHIFT)



  23. unsigned int BPM;                   // 用于保存脉冲速率
  24. unsigned int Signal;                // 持有传入的原始数据
  25. unsigned int IBI = 600;             // 保持心跳之间的空隙,必须种子!
  26. unsigned char Pulse = false;     // 当脉冲波高时真,低为假
  27. int rate[10];                    // 数组来保存最后十IBI值
  28. unsigned long sampleCounter = 0;          // used to determine pulse timing用于确定脉冲定时
  29. unsigned long lastBeatTime = 0;           // used to find IBI
  30. int Peak =255;                      // used to find peak in pulse wave, seeded用来寻找峰值脉冲波,播种
  31. int Trough = 10;                     // used to find trough in pulse wave, seededsed中找到谷底脉搏波,播种
  32. int thresh = 60;                // used to find instant moment of heart beat, seeded查找心跳的瞬间
  33. int amp = 100;                   // used to hold amplitude of pulse waveform, seeded用于保存脉冲波形的振幅,接种
  34. unsigned char firstBeat = true;        // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM
  35. unsigned char secondBeat = false;      // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM


  36. // Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
  37. //采样率500Hz
  38. unsigned char heartRateCalc(unsigned char buf,uint16* ratte)
  39. {                       
  40.   int N;
  41.   unsigned char i,j;

  42. unsigned char QS = false;                 // becomes true when 51 finds a beat.
  43. char cmd[100];
  44. uint16 len;

  45.         // keep a running total of the last 10 IBI values保持过去10 个心跳间隙值运行总数
  46.   unsigned int runningTotal = 0;                  // clear the runningTotal variable 清除正在运行的总变量  
  47.         j=0;
  48.         
  49.   Signal = buf;              // read the Pulse Sensor 读取脉搏传感器
  50.   sampleCounter += 2;                         // keep track of the time in mS with this variable追踪这个变量在毫秒级
  51.   N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise因为最后一次心跳监测时间可避免噪音
  52.   

  53.     //  找到脉搏波的波谷
  54.   if(Signal < thresh && N > (IBI/5)*3)
  55.   {       // 避免重脉噪声最后IBI等待4/5
  56.     if (Signal < Trough)
  57.         {                        // T is the trough;T是波谷
  58.       Trough = Signal;                         // 跟踪最低点的脉冲波
  59.     }
  60.   }

  61.   //  找到脉搏波的波峰

  62.   if(Signal > thresh && Signal > Peak)
  63.   {          // thresh condition helps avoid noise阈值条件有助于避免噪音
  64.     Peak = Signal;                             // P is the peak; P是峰
  65.   }                                        // keep track of highest point in pulse wave跟踪最高点的脉冲波


  66.   //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT 现在是时候去寻找心跳
  67.   // signal surges up in value every time there is a pulse每次有一个脉冲信号涌起的价值
  68.   if (N > 250)
  69.   {                                   // avoid high frequency noise 避免了高频噪音
  70.     if ( (Signal > thresh) && (Pulse == false) && (N > (IBI)*0.6) )
  71.         {        
  72.       Pulse = true;                               // set the Pulse flag when we think there is a pulse当我们认为有脉冲时设置脉冲标志
  73.     //  blinkPin=0;               // turn on pin 13 打开LED引脚
  74.       IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
  75.       lastBeatTime = sampleCounter;               // keep track of time for next pulse


  76.       if(secondBeat)
  77.           {                        // if this is the second beat, if secondBeat == TRUE
  78.         secondBeat = false;                  // clear secondBeat flag清零第二拍标志
  79.       //  for(i=0; i<=9; i++)
  80.                         //        {             // seed the running total to get a realisitic BPM at startup在启动时获得真实BPM运行总数
  81.       //    rate[9] = IBI;                     
  82.       //  }
  83.       }


  84.       if(firstBeat)
  85.           {                         // if it's the first time we found a beat, if firstBeat == TRUE
  86.         firstBeat = false;                   // clear firstBeat flag 清零第一拍标志
  87.         secondBeat = true;                   // set the second beat flag设置第二拍标志
  88.       //  EA=1;                               // enable interrupts again再次启用中断
  89.       Pulse = false;
  90.         return QS;                              // IBI value is unreliable so discard itIBI值是不可靠的,所以将其丢弃
  91.       }   

  92.                 BLUE_ON;
  93. //程序运行到这里表示已经找到第二个节拍
  94.                         //存放节拍的数组依次往前移位,留下最后一个来装新得到的节拍周期
  95.       for(i=0; i<=8; i++)
  96.           {                // shift data in the rate array移动数组中的数据
  97.         rate[i]= rate[i+1];                  // and drop the oldest IBI value 并删除最旧的IBI值
  98.         runningTotal += rate[i];              // add up the 9 oldest IBI values将9个最古老的IBI值加起来
  99.       }

  100. //存放最新的节拍周期
  101.       rate[9] = IBI;                          // add the latest IBI to the rate array添加最新IBI的速度阵列
  102.       runningTotal += rate[9];                // add the latest IBI to runningTotal加上最新的IBI运行数
  103.       runningTotal /= 10;                     // average the last 10 IBI values 平均最近10个IBI值
  104.       BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!有多少心跳可以放入一分钟?这是BPM的!
  105.             if(BPM>200)BPM=200;                        //限制BPM最高显示值
  106.             if(BPM<30)BPM=30;                                //限制BPM最低显示值
  107.       QS = true;                              // set Quantified Self flag 设置量化自我标志
  108.         len=sprintf(cmd,"Peak=%d,thresh=%d,Trough=%d,amp=%d,IBI=%d,N=%d,BPM=%d\r\n",Peak,thresh,Trough,amp,IBI,N,BPM);
  109. //        IntfWrite(0,cmd,len);
  110.       // QS FLAG IS NOT CLEARED INSIDE THIS ISR;  QS标志不会被清除这里面中断服务程序
  111.     }                       
  112.   }

  113. //检测下降
  114.   if (Signal < thresh && Pulse == true) // when the values are going down, the beat is over当值正在下降,节拍结束
  115.   {  
  116.           BLUE_OFF;// turn off pin 13 LED
  117.     Pulse = false;                         // reset the Pulse flag so we can do it again复位脉冲标志,所以我们可以再做一次
  118.     amp = Peak - Trough;                           // get amplitude of the pulse wave得到的脉搏波的振幅
  119.     thresh = amp/2 + Trough;                    // set thresh at 50% of the amplitude设定阈值的幅度的50%
  120.     Peak = thresh;                            // reset these for next time为下一次复位
  121.     Trough = thresh;
  122.         len=sprintf(cmd,"fall edge:Peak=%d,thresh=%d,Trough=%d,amp=%d,IBI=%d,N=%d,BPM=%d\r\n",Peak,thresh,Trough,amp,IBI,N,BPM);
  123. //        IntfWrite(0,cmd,len);
  124.   }

  125. //重新初始化
  126.   if (N > 2500)  // if 2.5 seconds go by without a beat 如果2.5秒去,没有一个节拍
  127.   {                        
  128.     thresh = 50;                          // set thresh default设置默认的阈值
  129.     Peak = 155;                               // set P default默认设置P
  130.     Trough = 10;                               // set T default默认设置T
  131.     lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date     最后一拍的时间   
  132.     firstBeat = true;                      // set these to avoid noise
  133.     secondBeat = false;                    // when we get the heartbeat back
  134.     Pulse = false;
  135.   }


  136.   //EA=1;                                   // enable interrupts when youre done!允许中断时,大功告成!
  137.   *ratte=BPM;
  138.   return QS;
  139. }// end isr
  140. void filter(uint8* buf,unsigned char len)
  141. {

  142. static uint8 x0=50,x1=50;
  143. uint8 i,temp;
  144. uint8 k=1,throd=10;
  145. uint8 Buff[BUFFER_SIZE+2];
  146.          uint8 buffback[BUFFER_SIZE];
  147.         memcpy(Buff+2,buf,len);
  148. //for(i=0;i<len;len++)
  149. //        Buff[i+2]=buf[i];
  150. Buff[0]=x0;
  151. Buff[1]=x1;

  152. for(i=0;i<len;len++)
  153.         if(abs(Buff[i+1]-Buff[i])>throd)
  154.                 buffback[i]=(Buff[i+2]+Buff[i])/2;
  155.         else
  156.                 buffback[i]=Buff[i+1];
  157. x0=Buff[BUFFER_SIZE];
  158. x1=Buff[BUFFER_SIZE+1];



  159. }
复制代码

所有资料51hei提供下载:
HeartRateTestPrj.7z (428.99 KB, 下载次数: 9)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2019-4-5 03:50 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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