找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6931|回复: 4
打印 上一主题 下一主题
收起左侧

pulsesensor心率计的51单片机源程序

  [复制链接]
跳转到指定楼层
楼主
芯片stc12c5a
采用清翔电子出品的QX-mini51开发板来配合pulsesensor心率传感器完成脉搏采集和心率计算。
文件中一共有三个程序,分别为:
1.pulsesensor_STC12C5A:仅使用电脑显示心率值
2.pulsesensor_STC12C5A_LCD1602:使用LCD1602和电脑显示心率值
3.pulsesensor_STC12C5A _LCD12864:使用LCD12864和电脑显示心率值
注意:使用前务必将短路块J1,J5,J6拿掉,不然会严重影响信号从而导致心率值不准!
可以保留短路块J2,此时LED1会跟随心跳闪烁。


单片机源程序如下:
  1. //******************************参数说明*********************************//
  2. //MCU:STC12C5A60S2
  3. //ADC PIN:P1.0
  4. //SYSTEM CLOCK:11.0592MHz
  5. //Baudrate:115200
  6. //UART:P3.0 P3.1
  7. //**********************************************************************//
  8. //******************************使用说明*********************************//
  9. //注意:使用前务必将短路块J1,J5,J6拿掉,不然会严重影响信号!
  10. //可以保留短路块J2,此时LED1会跟随心跳闪烁
  11. //**********************************************************************//
  12. #include <STC12C5A60S2.h>
  13. #include "stdio.h"
  14. #include <LCD12864.h>

  15. #define false 0
  16. #define true 1
  17. #define FOSC 11059200L                //系统时钟
  18. #define BAUD 115200                                //波特率
  19. #define T0MS (65536-FOSC/12/500)                //500HZ in 12T MODE

  20. #define ADC_POWER 0x80                        //ADC POWER CONTROL BIT
  21. #define ADC_FLAG 0x10                        //ADC COMPLETE FLAG
  22. #define ADC_START 0x08;                        //ADC START CONTROL BIT
  23. #define ADC_SPEEDLL 0x00                //540 CLOCKS
  24. #define ADC_SPEEDL 0x20                        //360 CLOCKS
  25. #define ADC_SPEEDH 0x40                        //180 CLOCKS
  26. #define ADC_SPEEDHH 0x60                //90 CLOCKS
  27. #define ADC_MASK 0x01

  28. void UART_init(void);
  29. void ADC_init(unsigned char channel);
  30. void T0_init(void);
  31. void sendDataToProcessing(char symbol, int dat);
  32. void UART_send(char dat);


  33. unsigned char PulsePin = 0;       // Pulse Sensor purple wire connected to analog pin 0(P1.0为AD口)
  34. //sbit blinkPin = P2^0;                // pin to blink led at each beat
  35. //sbit fadePin = P2^3;                  // pin to do fancy classy fading blink at each beat
  36. //sbit led1 = P2^1;
  37. //sbit led2 = P2^2;
  38. int fadeRate = 0;                 // used to fade LED on with PWM on fadePin


  39. // these variables are volatile because they are used during the interrupt service routine!
  40. volatile unsigned int BPM;                   // used to hold the pulse rate
  41. volatile unsigned int Signal;                // holds the incoming raw data
  42. volatile unsigned int IBI = 600;             // holds the time between beats, must be seeded!
  43. volatile bit Pulse = false;     // true when pulse wave is high, false when it's low
  44. volatile bit QS = false;        // becomes true when Arduoino finds a beat.
  45. volatile int rate[10];                    // array to hold last ten IBI values
  46. volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
  47. volatile unsigned long lastBeatTime = 0;           // used to find IBI
  48. volatile int Peak =512;                      // used to find peak in pulse wave, seeded
  49. volatile int Trough = 512;                     // used to find trough in pulse wave, seeded
  50. volatile int thresh = 512;                // used to find instant moment of heart beat, seeded
  51. volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
  52. volatile bit firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
  53. volatile bit secondBeat = false;      // used to seed rate array so we startup with reasonable BPM
  54. static unsigned char order=0;
  55. unsigned char code ucStr1[]  =  "Pulsesensor test";                //显示信息1
  56. unsigned char code ucStr2[]  =  "                ";                //显示信息2
  57. unsigned char code ucStr3[]  =  "  BPM:          ";                //显示信息3
  58. unsigned char code ucStr4[]  =  "作者:anning86525";                //显示信息4
  59. unsigned char DisBuff[4]={0};

  60. void sys_init()
  61. {
  62.         LCD12864_Init();   //初始化液晶
  63.   UART_init();             // we agree to talk fast!
  64.         ADC_init(PulsePin);
  65.   T0_init();                 // sets up to read Pulse Sensor signal every 2mS  
  66. }

  67. void main(void)
  68. {
  69.   sys_init();
  70.         LCD12864_DisplayOneLine(0x80,ucStr1);        //显示信息1
  71.         LCD12864_DisplayOneLine(0x90,ucStr2);        //显示信息2
  72.         LCD12864_DisplayOneLine(0x88,ucStr3);        //显示信息3
  73.         LCD12864_DisplayOneLine(0x98,ucStr4);        //显示信息4
  74.         while(1)
  75.         {
  76.                 sendDataToProcessing('S', Signal);     // send Processing the raw Pulse Sensor data
  77.                 if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat
  78.                                         fadeRate = 255;                  // Set 'fadeRate' Variable to 255 to fade LED with pulse
  79.                                         sendDataToProcessing('B',BPM);   // send heart rate with a 'B' prefix
  80.                                         sendDataToProcessing('Q',IBI);   // send time between beats with a 'Q' prefix
  81.                                         QS = false;                      // reset the Quantified Self flag for next time
  82.                                         LCD_disp_list_char(3,4,DisBuff);//在LCD12864上显示BPM
  83.                          }
  84.   
  85.   //ledFadeToBeat();

  86.   delay(138);                             //  take a break 19.6ms

  87. }
  88. }


  89. //void ledFadeToBeat(){
  90. //    fadeRate -= 15;                         //  set LED fade value
  91. //    fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!
  92. //    analogWrite(fadePin,fadeRate);          //  fade LED
  93. //  }


  94. void sendDataToProcessing(char symbol, int dat ){
  95.     putchar(symbol);                // symbol prefix tells Processing what type of data is coming
  96.                 printf("%d\r\n",dat);                                                // the data to send culminating in a carriage return
  97.   }

  98. void UART_init(void)
  99. {
  100.          PCON &= 0x7f;  //波特率不倍速
  101.    SCON = 0x50;  //8位数据,可变波特率
  102.    BRT = 0xFD;    //独立波特率产生器初值
  103.    AUXR |= 0x04;  //时钟设置为1T模式
  104.    AUXR |= 0x01;  //选择独立波特率产生器
  105.    AUXR |= 0x10;  //启动波特率产生
  106. }
  107. char putchar(unsigned char dat)
  108. {
  109.         TI=0;
  110.         SBUF=dat;
  111.         while(!TI);
  112.         TI=0;
  113.        
  114.         return SBUF;
  115. }




  116. void T0_init(void){     
  117.   // Initializes Timer0 to throw an interrupt every 2mS.
  118.         TMOD |= 0x01;        //16bit TIMER
  119.         TL0=T0MS;
  120.         TH0=T0MS>>8;
  121.         TR0=1;                //start Timer 0
  122.         ET0=1;                //enable Timer Interrupt
  123.   EA=1;             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED      
  124. }

  125. void ADC_init(unsigned char channel)
  126. {
  127.         P1ASF=ADC_MASK<<channel;        //enable PlusePin as ADC INPUT
  128.         ADC_RES=0;        //clear former ADC result
  129.         ADC_RESL=0;        //clear former ADC result
  130.         AUXR1 |= 0x04;        //adjust the format of ADC result
  131.         ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;        //power on ADC and start conversion
  132. }

  133. unsigned int analogRead(unsigned char channel)
  134. {
  135.         unsigned int result;

  136.         ADC_CONTR &=!ADC_FLAG;        //clear ADC FLAG
  137.         result=ADC_RES;
  138.         result=result<<8;
  139.         result+=ADC_RESL;
  140.         ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
  141.         return result;
  142. }
  143. // Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
  144. void Timer0_rountine(void) interrupt 1
  145. {                       
  146.   int N;
  147.         unsigned char i;
  148.         // keep a running total of the last 10 IBI values
  149.   unsigned int runningTotal = 0;                  // clear the runningTotal variable   

  150.         EA=0;                                      // disable interrupts while we do this
  151.         TL0=T0MS;
  152.         TH0=T0MS>>8;                                //reload 16 bit TIMER0
  153.   Signal = analogRead(PulsePin);              // read the Pulse Sensor
  154.   sampleCounter += 2;                         // keep track of the time in mS with this variable
  155.   N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise


  156.     //  find the peak and trough of the pulse wave
  157.   if(Signal < thresh && N > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
  158.     if (Signal < Trough){                        // T is the trough
  159.       Trough = Signal;                         // keep track of lowest point in pulse wave
  160.     }
  161.   }

  162.   if(Signal > thresh && Signal > Peak){          // thresh condition helps avoid noise
  163.     Peak = Signal;                             // P is the peak
  164.   }                                        // keep track of highest point in pulse wave

  165.   //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
  166.   // signal surges up in value every time there is a pulse
  167.   if (N > 250){                                   // avoid high frequency noise
  168.     if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
  169.       Pulse = true;                               // set the Pulse flag when we think there is a pulse
  170. //      blinkPin=0;               // turn on pin 13 LED
  171.       IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
  172.       lastBeatTime = sampleCounter;               // keep track of time for next pulse

  173.       if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
  174.         secondBeat = false;                  // clear secondBeat flag
  175.         for(i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
  176.           rate[i] = IBI;                     
  177.         }
  178.       }

  179.       if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
  180.         firstBeat = false;                   // clear firstBeat flag
  181.         secondBeat = true;                   // set the second beat flag
  182.         EA=1;                               // enable interrupts again
  183.         return;                              // IBI value is unreliable so discard it
  184.       }   



  185.       for(i=0; i<=8; i++){                // shift data in the rate array
  186.         rate[i] = rate[i+1];                  // and drop the oldest IBI value
  187.         runningTotal += rate[i];              // add up the 9 oldest IBI values
  188.       }

  189.       rate[9] = IBI;                          // add the latest IBI to the rate array
  190.       runningTotal += rate[9];                // add the latest IBI to runningTotal
  191.       runningTotal /= 10;                     // average the last 10 IBI values
  192.       BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
  193.                         if(BPM>200)BPM=200;                        //限制BPM最高显示值
  194.                         if(BPM<30)BPM=30;                                //限制BPM最低显示值
  195.                         DisBuff[2]   = BPM%10+48;//取个位数
  196. ……………………

  197. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
pulsesensor_STC12C5A.rar (803.8 KB, 下载次数: 198)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:568916 发表于 2019-7-1 20:01 | 只看该作者
有连接图吗?
回复

使用道具 举报

板凳
ID:579794 发表于 2019-7-10 09:11 | 只看该作者
芯片stc12c5a在新版proteus可以找到吗?
回复

使用道具 举报

地板
ID:872303 发表于 2021-1-2 19:46 | 只看该作者
可以只用lcd1602显示心率数值吗
回复

使用道具 举报

5#
ID:1111975 发表于 2024-3-10 14:25 | 只看该作者
第159行应该改成 ADC_CONTR &=~ADC_FLAG
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表