找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2496|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

最近在做STC15W4K32S4采集心率的實(shí)驗(yàn),調(diào)試了三天沒調(diào)試出來,希望有高手指點(diǎn)指點(diǎn)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:689493 發(fā)表于 2020-4-2 17:45 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
   采用的是STC15W4K32S4單片機(jī)作為處理器,心率模塊用的是Pulse sensor,只需要得出心跳次數(shù)BPM就行,其中AD轉(zhuǎn)換我用了P1.3口,通信用的是串口2(P1.0/RxD2    P1.1/TxD2), 另外,心率數(shù)據(jù)處理部分我參照了那個(gè)寶賣家給的Pulse sensor資料,不知道問題出在哪里了,一直沒調(diào)試出來(不需要上位機(jī)顯示,只需要得到心率值就行),希望有高手幫忙指點(diǎn)一下,謝謝了。下面代碼中我簡單注釋了一下。    再次謝謝大家了

    //系統(tǒng)頻率為11.0592MHz
#include<stc15.h>
#define u8 unsigned char
#define u16 unsigned int
#define false 0
#define true 1       
       
char bdata bit_S2CON;         //定義它主要是為了進(jìn)行位操作,我用的串口2
sbit TI_2 = bit_S2CON^1;               
sbit RI_2 = bit_S2CON^0;

u8 aa[3];            //定義它是為了存得出的心跳BPM(當(dāng)成3位數(shù)來處理,主要是方便串口通信傳輸它)

//下面這些定義是用在T0中斷中心率的處理,資料上是這樣的
volatile unsigned int BPM;                  //每分鐘的心跳
volatile unsigned int Signal;                //脈沖
volatile unsigned int IBI = 600;             //IBI是相鄰兩次心跳的時(shí)間間隔,600的意思應(yīng)該是0.6ms,我不太清楚
volatile bit Pulse = false;                  // 脈沖的標(biāo)志
volatile bit QS = false;                   // 這個(gè)是得出計(jì)算出了心跳次數(shù)BPM時(shí)候的一個(gè)標(biāo)志
volatile int rate[10];                    //定義成10位數(shù)組,主要是為了存10次心跳的間隔時(shí)間,然后為了求個(gè)平均值
volatile unsigned long sampleCounter = 0;         //上一次心跳的時(shí)間
volatile unsigned long lastBeatTime = 0;          //緊接著的下次心跳的時(shí)間,這兩個(gè)時(shí)間相減就是緊挨著的兩次心跳之間的時(shí)間
volatile int Peak =512;                    //脈沖峰值,這里資料上是512,我不清楚,是個(gè)脈沖中間值吧
volatile int Trough = 512;                 //脈沖的波谷
volatile int thresh = 512;               //波谷上升到波峰的那段的一個(gè)中間值,資料上意思是計(jì)算相鄰這樣的中間值來計(jì)算心跳準(zhǔn)確點(diǎn)
volatile int amp = 100;                   //用在波谷到波峰中間值的一個(gè)量,初值為什么是100,資料是這樣寫的
volatile bit firstBeat = true;           
volatile bit secondBeat = false;      //跟上面那個(gè)一樣是個(gè)標(biāo)志

void delay_ms(u16 z)                 //大概延時(shí)1ms的時(shí)間
{
        u8 x;
        for(; z > 0; z--)
                for(x = 110; x > 0; x--);
}

void Delay_6us()                //大概延時(shí)6us
{
        u8 i;
        i = 14;
        while (--i);
}

void ad_init()                            //ADC初始化 (STC15W4K32S4單片機(jī))
{
        ADC_CONTR |= 0x80;       //開啟ADC的電源
        delay_ms(1);                  //第一次開電源需要延時(shí)1ms,書上這樣寫的
        P1ASF |= 0x08;                  //將P1.3口作為AD功能
        ADC_CONTR |= 0x40;      //ADC轉(zhuǎn)換速度,我選擇額的是180個(gè)時(shí)鐘周期轉(zhuǎn)換一次,可以達(dá)10位精度
        Delay_6us();                 //每次執(zhí)行ADC_CONTR寄存器賦值時(shí),要延時(shí)一下,書上這樣介紹的
        CLK_DIV |= 0x20;      //這里我設(shè)置成轉(zhuǎn)換結(jié)果的高兩位存在ADC_RSE[1:0],轉(zhuǎn)換結(jié)果的低八位存在ADC_RESL[7:0]
}

u16 ad_work()                    //進(jìn)行AD轉(zhuǎn)換函數(shù),有返回值,需要對返回的結(jié)果進(jìn)行計(jì)算處理,得出心跳次數(shù)BPM
{
        u16 result;                    //定義它來存結(jié)果
        ADC_CONTR |= 0x03;        //選擇P1.3作為A/D輸入來用
        Delay_6us();
        ADC_CONTR |= 0x08;       //將開始轉(zhuǎn)換位ADC_START置1,開始進(jìn)行A/D轉(zhuǎn)換
        Delay_6us();
        while(!(ADC_CONTR & 0x10));    //判斷標(biāo)志位ADC_FLAG是否為1了,也就是是否A/D轉(zhuǎn)換完了
        ADC_CONTR &= 0xE7;           //轉(zhuǎn)換結(jié)束后將標(biāo)志ADC_FLAG和開始轉(zhuǎn)換位ADC_START置0;
        Delay_6us();
        result = ADC_RES;            
        result = result << 8;
        result = result + ADC_RESL;  //上面這幾行就是將結(jié)果存在result中
        return result;                 //返回值
}

void uart_init()              //串口2的初始化
{
        AUXR |= 0x04;                //采用定時(shí)器2,不分頻,它是固定為16位自動(dòng)重裝
        T2L = 0xFD;               
        T2H = 0x1F;                //裝初值設(shè)置波特率為9600
        AUXR |= 0x10;             //將TR2置1
        S2CON = 0x50;        //串口工作在方式2 , 8位數(shù)據(jù)
        EA = 1;

}

void uart_sendchar(u8 dat)            //發(fā)送單個(gè)字符
{
        S2BUF = dat;
        while(!(S2CON & 0x02));       //因?yàn)镾2CON不能被位尋址,所以這里用了前面定義的可以被位尋址的bit_S2CON
        bit_S2CON = S2CON;
        TI_2 = 0;
        S2CON = bit_S2CON;
}

void uart_sendstring(u8 *astring, u16 stringlength)        //發(fā)送數(shù)組,發(fā)送前面定義的aa[3],
{
        u8 i;
        for ( i = 0; i < stringlength; i++ )
        {
                uart_sendchar( astring[i] );
        }
}

void T0_init()                //定時(shí)器T0的初始化
{
        TMOD = 0x01;    //工作方式1,16位定時(shí)器
        TH0 = 0xF8;
        TL0 = 0xFC;       //定時(shí)2ms
        TR0 = 1;
        ET0 = 1;
        EA = 1;
}

void main()
{
        ad_init();
        uart_init();
        T0_init();
        while(1)                        //主函數(shù)里就只做將得到的心跳值BPM存在aa數(shù)組里,然后發(fā)送,,這兩件事情
        {
                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            //這個(gè)T0中斷里下面就是對AD轉(zhuǎn)換后的值做處理和運(yùn)算了,得到想要的心跳數(shù)BPM,那個(gè)寶老板給的資料
{                                                                //這資料里的就是這樣處理的,,不知道它程序邏輯有沒有問題,反正意思清楚,基本上沒怎么改動(dòng)它
       int N;
        unsigned char i;
       unsigned int runningTotal = 0;                     

        EA=0;                                      
        TH0 = 0xF8;
        TL0 = 0xFC;
  Signal = ad_work();                      //這個(gè)地方換成我自己的AD轉(zhuǎn)換后的結(jié)果,然后付給了初始信號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;                                                //這里這個(gè)QS就是得出心跳次數(shù)BPM后的標(biāo)志
    }                       
  }

  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;                                 
}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:721191 發(fā)表于 2020-4-2 19:04 | 只看該作者
程序代碼看看有沒有報(bào)錯(cuò),如果沒報(bào)錯(cuò),在protues上你試試運(yùn)行一下
回復(fù)

使用道具 舉報(bào)

板凳
ID:689493 發(fā)表于 2020-4-3 08:46 | 只看該作者
岸鞍 發(fā)表于 2020-4-2 19:04
程序代碼看看有沒有報(bào)錯(cuò),如果沒報(bào)錯(cuò),在protues上你試試運(yùn)行一下

沒有報(bào)錯(cuò)的,代碼中我已經(jīng)簡化了,只需要得到計(jì)算出來的BPM,通過串口把他發(fā)送出去就行,通過上位機(jī)Processing顯示波形我都省去了
回復(fù)

使用道具 舉報(bào)

地板
ID:689493 發(fā)表于 2020-4-3 08:52 | 只看該作者
岸鞍 發(fā)表于 2020-4-2 19:04
程序代碼看看有沒有報(bào)錯(cuò),如果沒報(bào)錯(cuò),在protues上你試試運(yùn)行一下

沒有報(bào)錯(cuò)的,其他什么傳送上位機(jī)processing顯示波形我都省去了,只需要通過串口傳輸計(jì)算出的心跳次數(shù)BPM就行,還是沒有結(jié)果,我單獨(dú)測試了AD功能,串口一直會(huì)收到'00 00 00 00 00'數(shù)據(jù)(是按照我預(yù)先設(shè)定時(shí)間運(yùn)行的)
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表