|
采用的是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;
}
|
|