//******************************说明********************************/
#include
#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口)
***it blinkPin = P2^0; // pin to blink led at each beat
***it fadePin = P2^3; // pin to do fancy classy fading blink at each beat
***it led1 = P2^1;
***it 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("%drn",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
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<
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
这是脉搏测量的一段单片机程序,现在跪求讲解!!!每一部分功能和总体流程图,尤其是脉搏的计算部分!!!!毕业答辩临近,程序没有看懂,求帮助!!!!
|