心率计可以将连接到板子上的心率传感器数据采集下来并使用算法计算心率值,并通过串口传输到指定的终端设备。可以直接接USB-TLL模块传输到PC端或者通过蓝牙模块传输到手机端。
单片机源程序如下:
- //******************************说明********************************/
- #include "stdio.h"
- #include "common.h"
- #include "heartRateProcess.h"
- #define false 0
- #define true 1
- #define FOSC 11059200L //系统时钟
- #define BAUD 115200 //波特率
- #define T0MS (65536-FOSC/12/500) //500HZ in 12T MODE
- #define BUFFER_SIZE 10
- #define ADC_POWER 0x80 //ADC POWER CONTROL BIT
- #define ADC_FLAG 0x10 //ADC COMPLETE FLAG
- #define ADC_START 0x08; //ADC START CONTROL BIT
- #define ADC_SPEEDLL 0x00 //540 CLOCKS
- #define ADC_SPEEDL 0x20 //360 CLOCKS
- #define ADC_SPEEDH 0x40 //180 CLOCKS
- #define ADC_SPEEDHH 0x60 //90 CLOCKS
- #define ADC_MASK 0x01
- #define BLUE_SHIFT (1U << 5)
- #define BLUE_ON (GPIOD_PCOR = BLUE_SHIFT)
- #define BLUE_OFF (GPIOD_PSOR = BLUE_SHIFT)
- #define BLUE_TOGGLE (GPIOD_PTOR = BLUE_SHIFT)
- unsigned int BPM; // 用于保存脉冲速率
- unsigned int Signal; // 持有传入的原始数据
- unsigned int IBI = 600; // 保持心跳之间的空隙,必须种子!
- unsigned char Pulse = false; // 当脉冲波高时真,低为假
- int rate[10]; // 数组来保存最后十IBI值
- unsigned long sampleCounter = 0; // used to determine pulse timing用于确定脉冲定时
- unsigned long lastBeatTime = 0; // used to find IBI
- int Peak =255; // used to find peak in pulse wave, seeded用来寻找峰值脉冲波,播种
- int Trough = 10; // used to find trough in pulse wave, seededsed中找到谷底脉搏波,播种
- int thresh = 60; // used to find instant moment of heart beat, seeded查找心跳的瞬间
- int amp = 100; // used to hold amplitude of pulse waveform, seeded用于保存脉冲波形的振幅,接种
- unsigned char firstBeat = true; // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM
- unsigned char secondBeat = false; // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM
- // Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
- //采样率500Hz
- unsigned char heartRateCalc(unsigned char buf,uint16* ratte)
- {
- int N;
- unsigned char i,j;
- unsigned char QS = false; // becomes true when 51 finds a beat.
- char cmd[100];
- uint16 len;
- // keep a running total of the last 10 IBI values保持过去10 个心跳间隙值运行总数
- unsigned int runningTotal = 0; // clear the runningTotal variable 清除正在运行的总变量
- j=0;
-
- Signal = buf; // read the Pulse Sensor 读取脉搏传感器
- sampleCounter += 2; // keep track of the time in mS with this variable追踪这个变量在毫秒级
- N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise因为最后一次心跳监测时间可避免噪音
-
- // 找到脉搏波的波谷
- if(Signal < thresh && N > (IBI/5)*3)
- { // 避免重脉噪声最后IBI等待4/5
- if (Signal < Trough)
- { // T is the trough;T是波谷
- Trough = Signal; // 跟踪最低点的脉冲波
- }
- }
- // 找到脉搏波的波峰
- if(Signal > thresh && Signal > Peak)
- { // thresh condition helps avoid noise阈值条件有助于避免噪音
- Peak = Signal; // P is the peak; P是峰
- } // keep track of highest point in pulse wave跟踪最高点的脉冲波
- // NOW IT'S TIME TO LOOK FOR THE HEART BEAT 现在是时候去寻找心跳
- // signal surges up in value every time there is a pulse每次有一个脉冲信号涌起的价值
- if (N > 250)
- { // avoid high frequency noise 避免了高频噪音
- if ( (Signal > thresh) && (Pulse == false) && (N > (IBI)*0.6) )
- {
- Pulse = true; // set the Pulse flag when we think there is a pulse当我们认为有脉冲时设置脉冲标志
- // blinkPin=0; // turn on pin 13 打开LED引脚
- IBI = sampleCounter - lastBeatTime; // measure time between beats in mS
- lastBeatTime = sampleCounter; // keep track of time for next pulse
- if(secondBeat)
- { // if this is the second beat, if secondBeat == TRUE
- secondBeat = false; // clear secondBeat flag清零第二拍标志
- // for(i=0; i<=9; i++)
- // { // seed the running total to get a realisitic BPM at startup在启动时获得真实BPM运行总数
- // rate[9] = IBI;
- // }
- }
- if(firstBeat)
- { // if it's the first time we found a beat, if firstBeat == TRUE
- firstBeat = false; // clear firstBeat flag 清零第一拍标志
- secondBeat = true; // set the second beat flag设置第二拍标志
- // EA=1; // enable interrupts again再次启用中断
- Pulse = false;
- return QS; // IBI value is unreliable so discard itIBI值是不可靠的,所以将其丢弃
- }
- BLUE_ON;
- //程序运行到这里表示已经找到第二个节拍
- //存放节拍的数组依次往前移位,留下最后一个来装新得到的节拍周期
- for(i=0; i<=8; i++)
- { // shift data in the rate array移动数组中的数据
- rate[i]= rate[i+1]; // and drop the oldest IBI value 并删除最旧的IBI值
- runningTotal += rate[i]; // add up the 9 oldest IBI values将9个最古老的IBI值加起来
- }
- //存放最新的节拍周期
- rate[9] = IBI; // add the latest IBI to the rate array添加最新IBI的速度阵列
- runningTotal += rate[9]; // add the latest IBI to runningTotal加上最新的IBI运行数
- runningTotal /= 10; // average the last 10 IBI values 平均最近10个IBI值
- BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!有多少心跳可以放入一分钟?这是BPM的!
- if(BPM>200)BPM=200; //限制BPM最高显示值
- if(BPM<30)BPM=30; //限制BPM最低显示值
- QS = true; // set Quantified Self flag 设置量化自我标志
- 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);
- // IntfWrite(0,cmd,len);
- // QS FLAG IS NOT CLEARED INSIDE THIS ISR; QS标志不会被清除这里面中断服务程序
- }
- }
- //检测下降
- if (Signal < thresh && Pulse == true) // when the values are going down, the beat is over当值正在下降,节拍结束
- {
- BLUE_OFF;// turn off pin 13 LED
- Pulse = false; // reset the Pulse flag so we can do it again复位脉冲标志,所以我们可以再做一次
- amp = Peak - Trough; // get amplitude of the pulse wave得到的脉搏波的振幅
- thresh = amp/2 + Trough; // set thresh at 50% of the amplitude设定阈值的幅度的50%
- Peak = thresh; // reset these for next time为下一次复位
- Trough = thresh;
- 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);
- // IntfWrite(0,cmd,len);
- }
- //重新初始化
- if (N > 2500) // if 2.5 seconds go by without a beat 如果2.5秒去,没有一个节拍
- {
- thresh = 50; // set thresh default设置默认的阈值
- Peak = 155; // set P default默认设置P
- Trough = 10; // set T default默认设置T
- lastBeatTime = sampleCounter; // bring the lastBeatTime up to date 最后一拍的时间
- firstBeat = true; // set these to avoid noise
- secondBeat = false; // when we get the heartbeat back
- Pulse = false;
- }
- //EA=1; // enable interrupts when youre done!允许中断时,大功告成!
- *ratte=BPM;
- return QS;
- }// end isr
- void filter(uint8* buf,unsigned char len)
- {
- static uint8 x0=50,x1=50;
- uint8 i,temp;
- uint8 k=1,throd=10;
- uint8 Buff[BUFFER_SIZE+2];
- uint8 buffback[BUFFER_SIZE];
- memcpy(Buff+2,buf,len);
- //for(i=0;i<len;len++)
- // Buff[i+2]=buf[i];
- Buff[0]=x0;
- Buff[1]=x1;
- for(i=0;i<len;len++)
- if(abs(Buff[i+1]-Buff[i])>throd)
- buffback[i]=(Buff[i+2]+Buff[i])/2;
- else
- buffback[i]=Buff[i+1];
- x0=Buff[BUFFER_SIZE];
- x1=Buff[BUFFER_SIZE+1];
- }
复制代码
所有资料51hei提供下载:
HeartRateTestPrj.7z
(428.99 KB, 下载次数: 9)
|