微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 脉搏测量程序求讲解

脉搏测量程序求讲解

时间:10-02 整理:3721RD 点击:
          //******************************说明********************************/

#include <STC12C5A60S2.h>
#include "stdio.h"

#define false 0
#define true 1
#define FOSC 11059200L                //系统时钟
#define BAUD 115200                                //波特率
#define T0MS (65536-FOSC/12/500)                //500HZ in 12T MODE

#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

//数码管段码显示:0~f,不亮
unsigned char code LED_Disp[] = {0xC0,0xF9,0xA4,0xB0,
                        0x99,0x92,0x82,0xF8,
                                                0x80,0x90,0x88,0x83,
                                                0xC6,0xA1,0x86,0x8E};

sfr LedPort = 0x80;         //段选段P0
sfr LedCtrl = 0xa0;         //位选段P2
unsigned char DisBuff[3];

void UART_init(void);
void LED_Disp_Seg7(void);
void ADC_init(unsigned char channel);
void T0_init(void);
void sendDataToProcessing(char symbol, int dat);
void delay(unsigned int n);
void UART_send(char dat);

unsigned char PulsePin = 0;       // Pulse Sensor purple wire connected to analog pin 0(P1.0为AD口)
sbit blinkPin = P2^0;                // pin to blink led at each beat
sbit fadePin = P2^3;                  // pin to do fancy classy fading blink at each beat
sbit led1 = P2^1;
sbit led2 = P2^2;
int fadeRate = 0;                 // used to fade LED on with PWM on fadePin


// 这些变量是不稳定的,因为它们是在中断服务程序中使用!
volatile unsigned int BPM;                   // 用于保存脉冲速率
volatile unsigned int Signal;                // 持有传入的原始数据
volatile unsigned int IBI = 600;             // 保持心跳之间的空隙,必须种子!
volatile bit Pulse = false;     // 当脉冲波高时真,低为假
volatile bit QS = false;        // becomes true when 51 finds a beat.
volatile int rate[10];                    // 数组来保存最后十IBI值
volatile unsigned long sampleCounter = 0;          // used to determine pulse timing用于确定脉冲定时
volatile unsigned long lastBeatTime = 0;           // used to find IBI
volatile int Peak =512;                      // used to find peak in pulse wave, seeded用来寻找峰值脉冲波,播种
volatile int Trough = 512;                     // used to find trough in pulse wave, seededsed中找到谷底脉搏波,播种
volatile int thresh = 512;                // used to find instant moment of heart beat, seeded查找心跳的瞬间
volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded用于保存脉冲波形的振幅,接种
volatile bit firstBeat = true;        // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM
volatile bit secondBeat = false;      // used to seed rate array so we startup with reasonable BPM用于种子率阵列,所以我们启动与合理的BPM
static unsigned char order=0;

void sys_init()
{
  //pinMode(blinkPin,OUTPUT);         // 随你的心跳引脚闪烁!
  //pinMode(fadePin,OUTPUT);          // 引脚灯显示你的心跳!
  UART_init();             // we agree to talk fast!
        ADC_init(PulsePin);
  T0_init();                 // 建立每2ms去读脉冲信号传感器
}

void main(void)
{
  sys_init();
        while(1)
        {
                sendDataToProcessing('S', Signal);     // send Processing the raw Pulse Sensor data发送传感器数据到processing
                if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat;Arduino发现心跳时量化自我标记为真
                                        fadeRate = 255;                  // Set 'fadeRate' Variable to 255 to fade LED with pulse设置'fadeRate'变到255减小LED脉冲
                                        sendDataToProcessing('B',BPM);   // send heart rate with a 'B' prefix发送心脏速率与'B'前缀
                                        sendDataToProcessing('Q',IBI);   // send time between beats with a 'Q' prefix送一个心跳的时间字头“Q”
                                        QS = false;                      // reset the Quantified Self flag for next time   下一次 重置量化自我标志
                         }
  
  //ledFadeToBeat();

  delay(138);                             //  take a break 19.6ms稍事休息19.6ms
}
}


//void ledFadeToBeat(){
//    fadeRate -= 15;                         //  set LED fade value
//    fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!保持LED值从负数进入!
//    analogWrite(fadePin,fadeRate);          //  fade LED
//  }


void sendDataToProcessing(char symbol, int dat ){
    putchar(symbol);                //符号前缀告诉处理什么类型的数据来了
                printf("%d\r\n",dat);        // 在回车发送高潮数据
  }

void UART_init(void)
{
         PCON &= 0x7f;  //波特率不倍速
   SCON = 0x50;  //8位数据,可变波特率
   BRT = 0xFD;    //独立波特率产生器初值
   AUXR |= 0x04;  //时钟设置为1T模式
   AUXR |= 0x01;  //选择独立波特率产生器
   AUXR |= 0x10;  //启动波特率产生
}
char putchar(unsigned char dat)
{
        TI=0;
        SBUF=dat;
        while(!TI);
        TI=0;
       
        return SBUF;
}
void delay(unsigned int n)
{
        unsigned int i,j;
        for(i=0;i<n;i++)
                for(j=0;j<100;j++);
}
void LED_Disp_Seg7(void)
{

  LedCtrl = LedCtrl | 0xf0;
        switch(order)
        {
                case 0:
                        LedPort = LED_Disp[DisBuff[0]];
                        LedCtrl = LedCtrl & 0x7f;
                        break;
                case 1:
                        LedPort = LED_Disp[DisBuff[1]];
                        LedCtrl = LedCtrl & 0xbf;
                        break;
                case 2:
                        if(DisBuff[2]==0)
                                LedCtrl = LedCtrl | 0xf0;
                        else
                        {
                                LedPort = LED_Disp[DisBuff[2]];
                                LedCtrl = LedCtrl & 0xdf;
                        }
                        break;
                default:
                        LedCtrl = LedCtrl | 0xf0;
        }
   if(++order>2)
                        order=0;
}




void T0_init(void){     
  // 初始化定时器0每2毫秒抛出一个中断.
        TMOD |= 0x01;        //16bit TIMER
        TL0=T0MS;
        TH0=T0MS>>8;
        TR0=1;                //start Timer 0
        ET0=1;                //enable Timer Interrupt
  EA=1;             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED   确定使能全局中断   
}

void ADC_init(unsigned char channel)
{
        P1ASF=ADC_MASK<<channel;        //enable PlusePin as ADC INPUT使脉搏传感器引脚作为ADC的输入
        ADC_RES=0;        //clear former ADC result清原ADC结果
        ADC_RESL=0;        //clear former ADC result清原ADC结果
        AUXR1 |= 0x04;        //adjust the format of ADC result调整ADC结果格式
        ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;        //power on ADC and start conversion电源ADC并开始转换
}

unsigned int analogRead(unsigned char channel)
{
        unsigned int result;

        ADC_CONTR &=!ADC_FLAG;        //clear ADC FLAG清除ADC标志
        result=ADC_RES;
        result=result<<8;
        result+=ADC_RESL;
        ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
        return result;
}
// Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
void Timer0_rountine(void) interrupt 1
{                       
  int N;
        unsigned char i;
        // keep a running total of the last 10 IBI values保持过去10 个心跳间隙值运行总数
  unsigned int runningTotal = 0;                  // clear the runningTotal variable 清除正在运行的总变量  

        EA=0;                                      // disable interrupts while we do this当我们这样做时禁止中断
        TL0=T0MS;
        TH0=T0MS>>8;                                //reload 16 bit TIMER0 重装16位定时器0
  Signal = analogRead(PulsePin);              // 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因为最后一次心跳监测时间可避免噪音
        LED_Disp_Seg7();


    //  找到脉搏波的波峰和波谷
  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/5)*3) ){        
      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 = 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再次启用中断
        return;                              // IBI value is unreliable so discard itIBI值是不可靠的,所以将其丢弃
      }   



      for(i=0; i<=8; i++){                // shift data in the rate array移动数组中的数据
        rate = rate[i+1];                  // and drop the oldest IBI value 并删除最旧的IBI值
        runningTotal += rate;              // 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最低显示值
                        DisBuff[0]   = BPM%10;//取个位数
                        DisBuff[1]   = BPM%100/10; //取十位数
                        DisBuff[2]   = BPM/100;           //百位数
      QS = true;                              // set Quantified Self flag 设置量化自我标志
      // QS FLAG IS NOT CLEARED INSIDE THIS ISR;  QS标志不会被清除这里面中断服务程序
    }                       
  }

  if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over当值正在下降,节拍结束
    blinkPin=1;            // 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;
  }

  if (N > 2500){                           // if 2.5 seconds go by without a beat 如果2.5秒去,没有一个节拍
    thresh = 512;                          // set thresh default设置默认的阈值
    Peak = 512;                               // set P default默认设置P
    Trough = 512;                               // 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
  }

  EA=1;                                   // enable interrupts when youre done!允许中断时,大功告成!
}// end isr
这是脉搏测量的一段单片机程序,现在跪求讲解!每一部分功能和总体流程图,尤其是脉搏的计算部分!毕业答辩临近,程序没有看懂,求帮助!

这个是你买的传感器配套过来的程序?

能发原理图么111111111111111111111111111111

请问IBI的初值为什么是600呢

这个程序是从Arduino程序中改过来的

我也是这个  跪求啊

6666666666666666666666666

能问一下,512这个值代表什么

我毕业设计也做的脉搏检测,求指教

我们的单片机课程设计也是这个,不仅有温度测量,时钟显示,还有脉搏测量

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top