|
僅供參考。
資料下載鏈接: https://pan.baidu.com/s/1m-6-WGiEGRARIZ4bVf4CrA 提取碼: 83fi
資料網(wǎng)盤下載:
鏈接:https://pan.baidu.com/s/1AIaHmvEXNmHU14CUYr4bhQ 提取碼:1f5a
鏈接: https://pan.baidu.com/s/1gfOU3o3 密碼: fr6q
- //******************************參數(shù)說(shuō)明*********************************//
- //MCU:STC12C5A60S2
- //ADC PIN:P1.0
- //SYSTEM CLOCK:11.0592MHz
- //Baudrate:115200
- //UART:P3.0 P3.1
- //**********************************************************************//
- //******************************使用說(shuō)明*********************************//
- //注意:使用前務(wù)必將短路塊J1,J5,J6拿掉,不然會(huì)嚴(yán)重影響信號(hào)!
- //可以保留短路塊J2,此時(shí)LED1會(huì)跟隨心跳閃爍
- //**********************************************************************//
- #include <STC12C5A60S2.h>
- #include "stdio.h"
- #define false 0
- #define true 1
- #define FOSC 11059200L //系統(tǒng)時(shí)鐘
- #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
- void UART_init(void);
- void ADC_init(unsigned char channel);
- void T0_init(void);
- void sendDataToProcessing(char symbol, int dat);
- void UART_send(char dat);
- void LCD12864_Init(void); //LCD12864初始化函數(shù)
- void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData); //向LCD12864寫入數(shù)據(jù),bComOrData為1時(shí)寫入的是數(shù)據(jù),0時(shí)寫入的是命令
- void LCD12864_CheckBusy(void); //忙檢測(cè)函數(shù)
- void LCD12864_DisplayOneLine(unsigned char ucPos,unsigned char *ucStr); //向LCD12864寫入一行文字
- void LCD12864_set_pos(unsigned char X,unsigned char Y);
- void LCD_disp_list_char(unsigned char X, unsigned char Y, char *DData);
- void delay(unsigned int uiCount);
- 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
- sbit LCD12864_RS = P0^7; //RS控制引腳
- sbit LCD12864_RW = P0^6; //RW控制引腳
- sbit LCD12864_EN = P0^5; //EN控制引腳
- sbit LCD12864_PSB = P0^4; //模式選擇引腳,ST7920控制器,1為8位并行接口,0為串行接口
- #define LCDPORT P2 //數(shù)據(jù)引腳
- // these variables are volatile because they are used during the interrupt service routine!
- volatile unsigned int BPM; // used to hold the pulse rate
- volatile unsigned int Signal; // holds the incoming raw data
- volatile unsigned int IBI = 600; // holds the time between beats, must be seeded!
- volatile bit Pulse = false; // true when pulse wave is high, false when it's low
- volatile bit QS = false; // becomes true when Arduoino finds a beat.
- volatile int rate[10]; // array to hold last ten IBI values
- 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, seeded
- 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
- volatile bit secondBeat = false; // used to seed rate array so we startup with reasonable BPM
- static unsigned char order=0;
- unsigned char code ucStr1[] = "Pulsesensor test"; //顯示信息1
- unsigned char code ucStr2[] = " "; //顯示信息2
- unsigned char code ucStr3[] = " BPM: "; //顯示信息3
- unsigned char code ucStr4[] = "作者:anning86525"; //顯示信息4
- unsigned char DisBuff[4]={0};
- /******************************************************************************
- 函數(shù)名稱:delay
- 函數(shù)功能:延時(shí)函數(shù)
- 入口參數(shù):uiCount-延時(shí)參數(shù)
- 返回值:無(wú)
- 備注:無(wú)
- *******************************************************************************/
- void delay(unsigned int n)
- {
- unsigned int i,j;
- for(i=0;i<n;i++)
- for(j=0;j<100;j++);
- }
- /******************************************************************************
- 函數(shù)名稱:LCD12864_WriteInfomation
- 函數(shù)功能:向LCD12864寫入命令或者數(shù)據(jù)
- 入口參數(shù):ucData-要寫入液晶的數(shù)據(jù)或者命令的內(nèi)容
- bComOrData-命令或者數(shù)據(jù)的標(biāo)志位選擇,0或者1,其中
- 1:寫入的是數(shù)據(jù)
- 0:寫入的是命令
- 返回值:無(wú)
- 備注: 無(wú)
- *******************************************************************************/
- void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData)
- {
- LCD12864_CheckBusy(); //忙檢測(cè)
- LCD12864_RW = 0; //拉低RW
- LCD12864_RS = bComOrData; //根據(jù)標(biāo)志位判斷寫入的是命令還是數(shù)據(jù)
- delay(15); //延時(shí),等待操作
- LCDPORT = ucData; //將數(shù)據(jù)送至數(shù)據(jù)端口
- LCD12864_EN = 1; //使能信號(hào)
- delay(15); //延時(shí)
- LCD12864_EN = 0; //按照時(shí)序來(lái)操作
- delay(15);
- }
- /******************************************************************************
- 函數(shù)名稱:LCD12864_Init
- 函數(shù)功能:LCD12864液晶初始化
- 入口參數(shù):無(wú)
- 返回值:無(wú)
- 備注:無(wú)
- *******************************************************************************/
- void LCD12864_Init(void)
- {
- delay(40);//延時(shí)
- LCD12864_PSB = 1; //8位并口工作模式
- delay(15);//延時(shí)
- LCD12864_WriteInfomation(0x30,0); //基本指令集
- delay(15);
- LCD12864_WriteInfomation(0x08,0); //顯示設(shè)置
- delay(15);
- LCD12864_WriteInfomation(0x10,0); //光標(biāo)設(shè)置
- delay(15);
- LCD12864_WriteInfomation(0x0c,0); //游標(biāo)設(shè)置
- delay(15);
- LCD12864_WriteInfomation(0x01,0); //清屏
- delay(15);
- LCD12864_WriteInfomation(0x06,0); //進(jìn)入點(diǎn)設(shè)定
- delay(15);
-
- }
- /******************************************************************************
- 函數(shù)名稱:LCD12864_CheckBusy
- 函數(shù)功能:忙檢測(cè)
- 入口參數(shù):無(wú)
- 返回值:無(wú)
- 備注:使用變量i做計(jì)時(shí),避免液晶在死循環(huán)處停滯。
- *******************************************************************************/
- void LCD12864_CheckBusy(void)
- {
- unsigned char i = 250; //局部變量
- LCD12864_RS = 0; //拉低
- LCD12864_RW = 1; //拉高
- LCD12864_EN = 1; //使能
- while((i > 0) && (P0 & 0x80))i--; //判斷忙標(biāo)志位
- LCD12864_EN = 0; //釋放
- }
- /******************************************************************************
- 函數(shù)名稱:LCD12864_DisplayOneLine
- 函數(shù)功能:顯示一行漢字(8個(gè)漢字或者16個(gè)英文字符)
- 入口參數(shù):position-要顯示的行的首地址,可選值0x80,0x88,0x90,0x98,其中:
- 0x80:液晶的第一行;
- 0x88:液晶的第三行;
- 0x90:液晶的第二行;
- 0x98:液晶的第四行。
- p-要顯示的內(nèi)容的首地址。
- 返回值:無(wú)
- 備注:無(wú)
- *******************************************************************************/
- void LCD12864_DisplayOneLine(unsigned char position,unsigned char *p)
- {
- unsigned char i;
- LCD12864_WriteInfomation(position,0);//寫入要顯示文字的行的首地址
- delay(15);
- for(i = 0;i<16;i++) //依次執(zhí)行寫入操作
- {
- LCD12864_WriteInfomation(*p,1);
- p++;
- }
- }
- /******************************************************************************
- 函數(shù)名稱:LCD12864_set_pos
- 函數(shù)功能:設(shè)定顯示位置
- 入口參數(shù):X-行數(shù),Y-列數(shù)
- 返回值:無(wú)
- 備注:無(wú)
- *******************************************************************************/
- void LCD12864_set_pos(unsigned char X,unsigned char Y)
- {
- unsigned char pos;
- if(X==1)
- X=0x80;
- else if(X==2)
- X=0x90;
- else if(X==3)
- X=0x88;
- else if(X==4)
- X=0x98;
-
- pos=X+Y;
- LCD12864_WriteInfomation(pos,0);
- }
- /*****************************************
- 函數(shù)名稱:LCD_disp_list_char
- 函數(shù)功能:在指定位置顯示內(nèi)容
- 入口參數(shù):X-行數(shù),Y-列數(shù),DData-顯示緩沖地址
- 返回值:無(wú)
- 備注:無(wú)
- *****************************************/
- void LCD_disp_list_char(unsigned char X, unsigned char Y, char *DData)
- {
- unsigned char ListLength;
-
- ListLength = 0;
- LCD12864_set_pos(X,Y);
- delay(15);
- while(DData[ListLength]!=0)
- {
- LCD12864_WriteInfomation(DData[ListLength],1);
- ListLength++;
- Y++;
- if(Y==16){
- Y = 0;
- X++;
- LCD12864_set_pos(X,Y);
- }
- }
- //輸出一行后發(fā)現(xiàn)結(jié)尾字符為英文字母,補(bǔ)一個(gè)空格
- if(ListLength%2){
- LCD12864_WriteInfomation(0,1);
- }
- return;
- }
- void sys_init()
- {
- LCD12864_Init(); //初始化液晶
- UART_init(); // we agree to talk fast!
- ADC_init(PulsePin);
- T0_init(); // sets up to read Pulse Sensor signal every 2mS
- }
- void main(void)
- {
- sys_init();
- LCD12864_DisplayOneLine(0x80,ucStr1); //顯示信息1
- LCD12864_DisplayOneLine(0x90,ucStr2); //顯示信息2
- LCD12864_DisplayOneLine(0x88,ucStr3); //顯示信息3
- LCD12864_DisplayOneLine(0x98,ucStr4); //顯示信息4
- while(1)
- {
- sendDataToProcessing('S', Signal); // send Processing the raw Pulse Sensor data
- if (QS == true){ // Quantified Self flag is true when arduino finds a heartbeat
- fadeRate = 255; // Set 'fadeRate' Variable to 255 to fade LED with pulse
- sendDataToProcessing('B',BPM); // send heart rate with a 'B' prefix
- sendDataToProcessing('Q',IBI); // send time between beats with a 'Q' prefix
- QS = false; // reset the Quantified Self flag for next time
- LCD_disp_list_char(3,4,DisBuff);//在LCD12864上顯示BPM
- }
- //ledFadeToBeat();
- delay(138); // take a break 19.6ms
- }
- }
- //void ledFadeToBeat(){
- // fadeRate -= 15; // set LED fade value
- // fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers!
- // analogWrite(fadePin,fadeRate); // fade LED
- // }
- void sendDataToProcessing(char symbol, int dat ){
- putchar(symbol); // symbol prefix tells Processing what type of data is coming
- printf("%d\r\n",dat); // the data to send culminating in a carriage return
- }
- void UART_init(void)
- {
- PCON &= 0x7f; //波特率不倍速
- SCON = 0x50; //8位數(shù)據(jù),可變波特率
- BRT = 0xFD; //獨(dú)立波特率產(chǎn)生器初值
- AUXR |= 0x04; //時(shí)鐘設(shè)置為1T模式
- AUXR |= 0x01; //選擇獨(dú)立波特率產(chǎn)生器
- AUXR |= 0x10; //啟動(dòng)波特率產(chǎn)生
- }
- char putchar(unsigned char dat)
- {
- TI=0;
- SBUF=dat;
- while(!TI);
- TI=0;
-
- return SBUF;
- }
- void T0_init(void){
- // Initializes Timer0 to throw an interrupt every 2mS.
- 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_RES=0; //clear former ADC result
- ADC_RESL=0; //clear former ADC result
- AUXR1 |= 0x04; //adjust the format of ADC result
- ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START; //power on ADC and start conversion
- }
- unsigned int analogRead(unsigned char channel)
- {
- unsigned int result;
- ADC_CONTR &=!ADC_FLAG; //clear ADC FLAG
- result=ADC_RES;
- result=result<<8;
- result+=ADC_RESL;
- ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
- return result;
- }
- // Timer 0中斷子程序,每2MS中斷一次,讀取AD值,計(jì)算心率值
- void Timer0_rountine(void) interrupt 1
- {
- int N;
- unsigned char i;
- // keep a running total of the last 10 IBI values
- 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
- 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
- // find the peak and trough of the pulse wave
- if(Signal < thresh && N > (IBI/5)*3){ // avoid dichrotic noise by waiting 3/5 of last IBI
- if (Signal < Trough){ // T is the trough
- Trough = Signal; // keep track of lowest point in pulse wave
- }
- }
- if(Signal > thresh && Signal > Peak){ // thresh condition helps avoid noise
- Peak = Signal; // P is the peak
- } // 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
- rate[i] = 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 it
- }
- for(i=0; i<=8; i++){ // shift data in the rate array
- rate[i] = rate[i+1]; // and drop the oldest IBI value
- runningTotal += rate[i]; // add up the 9 oldest IBI values
- }
- rate[9] = IBI; // add the latest IBI to the rate array
- runningTotal += rate[9]; // add the latest IBI to runningTotal
- runningTotal /= 10; // average the last 10 IBI values
- BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!
- if(BPM>200)BPM=200; //限制BPM最高顯示值
- if(BPM<30)BPM=30; //限制BPM最低顯示值
- DisBuff[2] = BPM%10+48;//取個(gè)位數(shù)
- DisBuff[1] = BPM%100/10+48; //取十位數(shù)
- DisBuff[0] = BPM/100+48; //百位數(shù)
- if(DisBuff[0]==48)
- DisBuff[0]=32;
- QS = true; // set Quantified Self flag
- // QS FLAG IS NOT CLEARED INSIDE THIS ISR
- }
- }
- 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
- Peak = thresh; // reset these for next time
- Trough = thresh;
- }
- if (N > 2500){ // if 2.5 seconds go by without a beat
- thresh = 512; // set thresh default
- Peak = 512; // set P default
- Trough = 512; // set T default
- 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
復(fù)制代碼 |
|