|
采用的是STC15W4K32S4单片机作为处理器,心率模块用的是Pulse sensor,只需要得出心跳次数BPM就行,其中AD转换我用了P1.3口,通信用的是串口2(P1.0/RxD2 P1.1/TxD2), 另外,心率数据处理部分我参照了那个宝卖家给的Pulse sensor资料,不知道问题出在哪里了,一直没调试出来(不需要上位机显示,只需要得到心率值就行),希望有高手帮忙指点一下,谢谢了。下面代码中我简单注释了一下。 再次谢谢大家了
//系统频率为11.0592MHz
#include<stc15.h>
#define u8 unsigned char
#define u16 unsigned int
#define false 0
#define true 1
char bdata bit_S2CON; //定义它主要是为了进行位操作,我用的串口2
sbit TI_2 = bit_S2CON^1;
sbit RI_2 = bit_S2CON^0;
u8 aa[3]; //定义它是为了存得出的心跳BPM(当成3位数来处理,主要是方便串口通信传输它)
//下面这些定义是用在T0中断中心率的处理,资料上是这样的
volatile unsigned int BPM; //每分钟的心跳
volatile unsigned int Signal; //脉冲
volatile unsigned int IBI = 600; //IBI是相邻两次心跳的时间间隔,600的意思应该是0.6ms,我不太清楚
volatile bit Pulse = false; // 脉冲的标志
volatile bit QS = false; // 这个是得出计算出了心跳次数BPM时候的一个标志
volatile int rate[10]; //定义成10位数组,主要是为了存10次心跳的间隔时间,然后为了求个平均值
volatile unsigned long sampleCounter = 0; //上一次心跳的时间
volatile unsigned long lastBeatTime = 0; //紧接着的下次心跳的时间,这两个时间相减就是紧挨着的两次心跳之间的时间
volatile int Peak =512; //脉冲峰值,这里资料上是512,我不清楚,是个脉冲中间值吧
volatile int Trough = 512; //脉冲的波谷
volatile int thresh = 512; //波谷上升到波峰的那段的一个中间值,资料上意思是计算相邻这样的中间值来计算心跳准确点
volatile int amp = 100; //用在波谷到波峰中间值的一个量,初值为什么是100,资料是这样写的
volatile bit firstBeat = true;
volatile bit secondBeat = false; //跟上面那个一样是个标志
void delay_ms(u16 z) //大概延时1ms的时间
{
u8 x;
for(; z > 0; z--)
for(x = 110; x > 0; x--);
}
void Delay_6us() //大概延时6us
{
u8 i;
i = 14;
while (--i);
}
void ad_init() //ADC初始化 (STC15W4K32S4单片机)
{
ADC_CONTR |= 0x80; //开启ADC的电源
delay_ms(1); //第一次开电源需要延时1ms,书上这样写的
P1ASF |= 0x08; //将P1.3口作为AD功能
ADC_CONTR |= 0x40; //ADC转换速度,我选择额的是180个时钟周期转换一次,可以达10位精度
Delay_6us(); //每次执行ADC_CONTR寄存器赋值时,要延时一下,书上这样介绍的
CLK_DIV |= 0x20; //这里我设置成转换结果的高两位存在ADC_RSE[1:0],转换结果的低八位存在ADC_RESL[7:0]
}
u16 ad_work() //进行AD转换函数,有返回值,需要对返回的结果进行计算处理,得出心跳次数BPM
{
u16 result; //定义它来存结果
ADC_CONTR |= 0x03; //选择P1.3作为A/D输入来用
Delay_6us();
ADC_CONTR |= 0x08; //将开始转换位ADC_START置1,开始进行A/D转换
Delay_6us();
while(!(ADC_CONTR & 0x10)); //判断标志位ADC_FLAG是否为1了,也就是是否A/D转换完了
ADC_CONTR &= 0xE7; //转换结束后将标志ADC_FLAG和开始转换位ADC_START置0;
Delay_6us();
result = ADC_RES;
result = result << 8;
result = result + ADC_RESL; //上面这几行就是将结果存在result中
return result; //返回值
}
void uart_init() //串口2的初始化
{
AUXR |= 0x04; //采用定时器2,不分频,它是固定为16位自动重装
T2L = 0xFD;
T2H = 0x1F; //装初值设置波特率为9600
AUXR |= 0x10; //将TR2置1
S2CON = 0x50; //串口工作在方式2 , 8位数据
EA = 1;
}
void uart_sendchar(u8 dat) //发送单个字符
{
S2BUF = dat;
while(!(S2CON & 0x02)); //因为S2CON不能被位寻址,所以这里用了前面定义的可以被位寻址的bit_S2CON
bit_S2CON = S2CON;
TI_2 = 0;
S2CON = bit_S2CON;
}
void uart_sendstring(u8 *astring, u16 stringlength) //发送数组,发送前面定义的aa[3],
{
u8 i;
for ( i = 0; i < stringlength; i++ )
{
uart_sendchar( astring[i] );
}
}
void T0_init() //定时器T0的初始化
{
TMOD = 0x01; //工作方式1,16位定时器
TH0 = 0xF8;
TL0 = 0xFC; //定时2ms
TR0 = 1;
ET0 = 1;
EA = 1;
}
void main()
{
ad_init();
uart_init();
T0_init();
while(1) //主函数里就只做将得到的心跳值BPM存在aa数组里,然后发送,,这两件事情
{
if(QS == true)
{
QS = false;
aa[0] = BPM/100;
aa[1] = BPM%100/10;
aa[2] = BPM%100%10;
uart_sendstring(aa,3);
}
}
}
void Timer0_rountine(void) interrupt 1 //这个T0中断里下面就是对AD转换后的值做处理和运算了,得到想要的心跳数BPM,那个宝老板给的资料
{ //这资料里的就是这样处理的,,不知道它程序逻辑有没有问题,反正意思清楚,基本上没怎么改动它
int N;
unsigned char i;
unsigned int runningTotal = 0;
EA=0;
TH0 = 0xF8;
TL0 = 0xFC;
Signal = ad_work(); //这个地方换成我自己的AD转换后的结果,然后付给了初始信号Signal
sampleCounter += 2;
N = sampleCounter - lastBeatTime;
if(Signal < thresh && N > (IBI/5)*3){
if (Signal < Trough){
Trough = Signal;
}
}
if(Signal > thresh && Signal > Peak){
Peak = Signal;
}
if (N > 250){
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){
Pulse = true;
IBI = sampleCounter - lastBeatTime;
lastBeatTime = sampleCounter;
if(secondBeat){
secondBeat = false;
for(i=0; i<=9; i++){
rate[i] = IBI;
}
}
if(firstBeat){
firstBeat = false;
secondBeat = true;
EA=1;
return;
}
for(i=0; i<=8; i++){
rate[i] = rate[i+1];
runningTotal += rate[i];
}
rate[9] = IBI;
runningTotal += rate[9];
runningTotal /= 10;
BPM = 60000/runningTotal;
if(BPM>200)BPM=200;
if(BPM<30)BPM=30;
QS = true; //这里这个QS就是得出心跳次数BPM后的标志
}
}
if (Signal < thresh && Pulse == true){
Pulse = false;
amp = Peak - Trough;
thresh = amp/2 + Trough;
Peak = thresh;
Trough = thresh;
}
if (N > 2500){
thresh = 512;
Peak = 512;
Trough = 512;
lastBeatTime = sampleCounter;
firstBeat = true;
secondBeat = false;
}
EA=1;
}
|
|