找回密码
 立即注册

QQ登录

只需一步,快速开始

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

脉搏心率检测hex文件(液晶同步波形显示)缺少源码

[复制链接]
跳转到指定楼层
楼主
    脉搏传感器是用来测试心跳速率的传感器,学生、艺术家、运动员、创造者、游戏或者移动终端开发人员,可以开发出和心率有关
的相关作品。传感器可以戴在手指或者耳垂上,通过接线可以与单
片机相连。通过12864液晶可以实时的把您的心率用图线显示出来。
下面模块是一款
集成了放大电路和噪声消除电路的光学心率传感器。







硬件选择
1、单片机  STC 12C5A60S2
2、液晶 LCD12864(汉字库)
3、51最小系统或51开发板一块
4、心率传感器模块

液晶硬件连接
   sbit       CE    =P2^2;
   sbit       RW   =P2^1;
   sbit       RS    =P2^0;
   #define  DATA_PORT        P0

心率传感器连接
    P0^0

单片机 HEX 文件下载(缺少源码,请勿下载)
    心率检测.rar (3.5 KB, 下载次数: 23)

扩展功能
    1、心率波形可以同步上位机显示
    2、心率波形可以同步安卓APP显示





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

使用道具 举报

沙发
ID:684376 发表于 2020-1-9 22:14 | 只看该作者
您好,可以分享一下源码吗,感想
回复

使用道具 举报

板凳
ID:661907 发表于 2021-4-5 23:35 | 只看该作者
博主您好,请问可以免费分享一下吗?非常感谢
回复

使用道具 举报

地板
ID:924572 发表于 2022-1-20 20:52 | 只看该作者
请问 有max30102 proteus仿真吗?
回复

使用道具 举报

5#
ID:425825 发表于 2022-1-21 21:22 | 只看该作者
max30102 是不能仿真的,我这里有max30102实物,通过TTL串口发送测量结果,需要的话,可以联系
回复

使用道具 举报

6#
ID:155507 发表于 2022-6-2 10:12 | 只看该作者
仅供参考。

资料下载链接: https://pan.baidu.com/s/1m-6-WGiEGRARIZ4bVf4CrA 提取码: 83fi

资料网盘下载:

链接:https://pan.baidu.com/s/1AIaHmvEXNmHU14CUYr4bhQ 提取码:1f5a

链接: https://pan.baidu.com/s/1gfOU3o3 密码: fr6q


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

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

  27. void UART_init(void);
  28. void ADC_init(unsigned char channel);
  29. void T0_init(void);
  30. void sendDataToProcessing(char symbol, int dat);
  31. void UART_send(char dat);
  32. void LCD12864_Init(void);                  //LCD12864初始化函数
  33. void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData);           //向LCD12864写入数据,bComOrData为1时写入的是数据,0时写入的是命令
  34. void LCD12864_CheckBusy(void);                //忙检测函数
  35. void LCD12864_DisplayOneLine(unsigned char ucPos,unsigned char *ucStr);          //向LCD12864写入一行文字
  36. void LCD12864_set_pos(unsigned char X,unsigned char Y);
  37. void LCD_disp_list_char(unsigned char X, unsigned char Y, char *DData);
  38. void delay(unsigned int uiCount);


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

  45. sbit LCD12864_RS  =  P0^7;         //RS控制引脚
  46. sbit LCD12864_RW  =  P0^6;         //RW控制引脚
  47. sbit LCD12864_EN  =  P0^5;         //EN控制引脚
  48. sbit LCD12864_PSB  =  P0^4;          //模式选择引脚,ST7920控制器,1为8位并行接口,0为串行接口
  49. #define LCDPORT P2                //数据引脚


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


  71. /******************************************************************************
  72. 函数名称:delay
  73. 函数功能:延时函数
  74. 入口参数:uiCount-延时参数
  75. 返回值:无
  76. 备注:无
  77. *******************************************************************************/
  78. void delay(unsigned int n)
  79. {
  80.         unsigned int i,j;
  81.         for(i=0;i<n;i++)
  82.             for(j=0;j<100;j++);
  83. }


  84. /******************************************************************************
  85. 函数名称:LCD12864_WriteInfomation
  86. 函数功能:向LCD12864写入命令或者数据
  87. 入口参数:ucData-要写入液晶的数据或者命令的内容
  88.                   bComOrData-命令或者数据的标志位选择,0或者1,其中
  89.                         1:写入的是数据
  90.                         0:写入的是命令
  91. 返回值:无
  92. 备注:  无
  93. *******************************************************************************/
  94. void LCD12864_WriteInfomation(unsigned char ucData,bit bComOrData)
  95. {
  96.         LCD12864_CheckBusy();          //忙检测
  97.         LCD12864_RW = 0;              //拉低RW
  98.         LCD12864_RS = bComOrData;        //根据标志位判断写入的是命令还是数据
  99.         delay(15);                                  //延时,等待操作
  100.         LCDPORT = ucData;                  //将数据送至数据端口
  101.         LCD12864_EN = 1;                  //使能信号
  102.         delay(15);                                  //延时
  103.         LCD12864_EN = 0;                //按照时序来操作
  104.         delay(15);
  105. }

  106. /******************************************************************************
  107. 函数名称:LCD12864_Init
  108. 函数功能:LCD12864液晶初始化
  109. 入口参数:无
  110. 返回值:无
  111. 备注:无
  112. *******************************************************************************/
  113. void LCD12864_Init(void)
  114. {
  115.         delay(40);//延时
  116.         LCD12864_PSB = 1;        //8位并口工作模式
  117.         delay(15);//延时


  118.         LCD12864_WriteInfomation(0x30,0); //基本指令集
  119.         delay(15);
  120.         LCD12864_WriteInfomation(0x08,0);  //显示设置
  121.         delay(15);
  122.         LCD12864_WriteInfomation(0x10,0);        //光标设置
  123.         delay(15);
  124.         LCD12864_WriteInfomation(0x0c,0);        //游标设置
  125.         delay(15);
  126.         LCD12864_WriteInfomation(0x01,0);  //清屏
  127.         delay(15);
  128.         LCD12864_WriteInfomation(0x06,0);        //进入点设定
  129.         delay(15);
  130.        
  131. }

  132. /******************************************************************************
  133. 函数名称:LCD12864_CheckBusy
  134. 函数功能:忙检测
  135. 入口参数:无
  136. 返回值:无
  137. 备注:使用变量i做计时,避免液晶在死循环处停滞。
  138. *******************************************************************************/
  139. void LCD12864_CheckBusy(void)
  140. {
  141.         unsigned char i = 250;        //局部变量
  142.         LCD12864_RS = 0;          //拉低
  143.         LCD12864_RW = 1;          //拉高
  144.         LCD12864_EN = 1;          //使能
  145.         while((i > 0) && (P0 & 0x80))i--;  //判断忙标志位
  146.         LCD12864_EN = 0;          //释放
  147. }

  148. /******************************************************************************
  149. 函数名称:LCD12864_DisplayOneLine
  150. 函数功能:显示一行汉字(8个汉字或者16个英文字符)
  151. 入口参数:position-要显示的行的首地址,可选值0x80,0x88,0x90,0x98,其中:
  152.                         0x80:液晶的第一行;
  153.                         0x88:液晶的第三行;
  154.                         0x90:液晶的第二行;
  155.                         0x98:液晶的第四行。
  156.                 p-要显示的内容的首地址。
  157. 返回值:无
  158. 备注:无
  159. *******************************************************************************/
  160. void LCD12864_DisplayOneLine(unsigned char position,unsigned char *p)
  161. {
  162.         unsigned char i;
  163.         LCD12864_WriteInfomation(position,0);//写入要显示文字的行的首地址
  164.         delay(15);

  165.         for(i = 0;i<16;i++)                //依次执行写入操作
  166.         {
  167.                 LCD12864_WriteInfomation(*p,1);
  168.                 p++;
  169.         }
  170. }
  171. /******************************************************************************
  172. 函数名称:LCD12864_set_pos
  173. 函数功能:设定显示位置
  174. 入口参数:X-行数,Y-列数
  175. 返回值:无
  176. 备注:无
  177. *******************************************************************************/
  178. void LCD12864_set_pos(unsigned char X,unsigned char Y)
  179. {
  180.         unsigned char pos;
  181.         if(X==1)
  182.         X=0x80;
  183.         else if(X==2)
  184.         X=0x90;
  185.         else if(X==3)
  186.         X=0x88;
  187.         else if(X==4)
  188.         X=0x98;
  189.        
  190.         pos=X+Y;
  191.         LCD12864_WriteInfomation(pos,0);
  192. }
  193. /*****************************************
  194. 函数名称:LCD_disp_list_char
  195. 函数功能:在指定位置显示内容
  196. 入口参数:X-行数,Y-列数,DData-显示缓冲地址
  197. 返回值:无
  198. 备注:无
  199. *****************************************/
  200. void LCD_disp_list_char(unsigned char X, unsigned char Y, char *DData)
  201. {
  202.         unsigned char ListLength;
  203.        
  204.         ListLength = 0;
  205.         LCD12864_set_pos(X,Y);
  206.         delay(15);
  207.         while(DData[ListLength]!=0)
  208.         {
  209.                 LCD12864_WriteInfomation(DData[ListLength],1);
  210.                 ListLength++;
  211.                 Y++;
  212.                 if(Y==16){
  213.                         Y = 0;
  214.                         X++;
  215.                         LCD12864_set_pos(X,Y);
  216.                 }
  217.         }
  218.         //输出一行后发现结尾字符为英文字母,补一个空格
  219.         if(ListLength%2){
  220.                 LCD12864_WriteInfomation(0,1);
  221.         }
  222.         return;
  223. }


  224. void sys_init()
  225. {
  226.         LCD12864_Init();   //初始化液晶
  227.         UART_init();             // we agree to talk fast!
  228.         ADC_init(PulsePin);
  229.         T0_init();                 // sets up to read Pulse Sensor signal every 2mS  
  230. }

  231. void main(void)
  232. {
  233.         sys_init();
  234.         LCD12864_DisplayOneLine(0x80,ucStr1);        //显示信息1
  235.         LCD12864_DisplayOneLine(0x90,ucStr2);        //显示信息2
  236.         LCD12864_DisplayOneLine(0x88,ucStr3);        //显示信息3
  237.         LCD12864_DisplayOneLine(0x98,ucStr4);        //显示信息4
  238.         while(1)
  239.         {
  240.                 sendDataToProcessing('S', Signal);     // send Processing the raw Pulse Sensor data
  241.                 if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat
  242.                         fadeRate = 255;                  // Set 'fadeRate' Variable to 255 to fade LED with pulse
  243.                         sendDataToProcessing('B',BPM);   // send heart rate with a 'B' prefix
  244.                         sendDataToProcessing('Q',IBI);   // send time between beats with a 'Q' prefix
  245.                         QS = false;                      // reset the Quantified Self flag for next time
  246.                         LCD_disp_list_char(3,4,DisBuff);//在LCD12864上显示BPM
  247.                 }

  248.                 //ledFadeToBeat();

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

  250.         }
  251. }


  252. //void ledFadeToBeat(){
  253. //    fadeRate -= 15;                         //  set LED fade value
  254. //    fadeRate = constrain(fadeRate,0,255);   //  keep LED fade value from going into negative numbers!
  255. //    analogWrite(fadePin,fadeRate);          //  fade LED
  256. //  }


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

  261. void UART_init(void)
  262. {
  263.         PCON &= 0x7f;  //波特率不倍速
  264.         SCON = 0x50;  //8位数据,可变波特率
  265.         BRT = 0xFD;    //独立波特率产生器初值
  266.         AUXR |= 0x04;  //时钟设置为1T模式
  267.         AUXR |= 0x01;  //选择独立波特率产生器
  268.         AUXR |= 0x10;  //启动波特率产生
  269. }
  270. char putchar(unsigned char dat)
  271. {
  272.         TI=0;
  273.         SBUF=dat;
  274.         while(!TI);
  275.         TI=0;
  276.        
  277.         return SBUF;
  278. }




  279. void T0_init(void){     
  280.         // Initializes Timer0 to throw an interrupt every 2mS.
  281.         TMOD |= 0x01;        //16bit TIMER
  282.         TL0=T0MS;
  283.         TH0=T0MS>>8;
  284.         TR0=1;                //start Timer 0
  285.         ET0=1;                //enable Timer Interrupt
  286.         EA=1;             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED      
  287. }

  288. void ADC_init(unsigned char channel)
  289. {
  290.         P1ASF=ADC_MASK<<channel;        //enable PlusePin as ADC INPUT
  291.         ADC_RES=0;        //clear former ADC result
  292.         ADC_RESL=0;        //clear former ADC result
  293.         AUXR1 |= 0x04;        //adjust the format of ADC result
  294.         ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;        //power on ADC and start conversion
  295. }

  296. unsigned int analogRead(unsigned char channel)
  297. {
  298.         unsigned int result;

  299.         ADC_CONTR &=!ADC_FLAG;        //clear ADC FLAG
  300.         result=ADC_RES;
  301.         result=result<<8;
  302.         result+=ADC_RESL;
  303.         ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
  304.         return result;
  305. }
  306. // Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
  307. void Timer0_rountine(void) interrupt 1
  308. {                       
  309.         int N;
  310.         unsigned char i;
  311.         // keep a running total of the last 10 IBI values
  312.         unsigned int runningTotal = 0;                  // clear the runningTotal variable   

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


  319.         //  find the peak and trough of the pulse wave
  320.         if(Signal < thresh && N > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
  321.                 if (Signal < Trough){                        // T is the trough
  322.                         Trough = Signal;                         // keep track of lowest point in pulse wave
  323.                 }
  324.         }

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

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

  336.                         if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
  337.                                 secondBeat = false;                  // clear secondBeat flag
  338.                                 for(i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
  339.                                         rate[i] = IBI;                     
  340.                                 }
  341.                         }

  342.                         if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
  343.                                 firstBeat = false;                   // clear firstBeat flag
  344.                                 secondBeat = true;                   // set the second beat flag
  345.                                 EA=1;                               // enable interrupts again
  346.                                 return;                              // IBI value is unreliable so discard it
  347.                         }   



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

  352.                         rate[9] = IBI;                          // add the latest IBI to the rate array
  353.                         runningTotal += rate[9];                // add the latest IBI to runningTotal
  354.                         runningTotal /= 10;                     // average the last 10 IBI values
  355.                         BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
  356.                         if(BPM>200)BPM=200;                        //限制BPM最高显示值
  357.                         if(BPM<30)BPM=30;                                //限制BPM最低显示值
  358.                         DisBuff[2]   = BPM%10+48;//取个位数
  359.                         DisBuff[1]   = BPM%100/10+48; //取十位数
  360.                         DisBuff[0]   = BPM/100+48;           //百位数
  361.                         if(DisBuff[0]==48)
  362.                         DisBuff[0]=32;
  363.                         QS = true;                              // set Quantified Self flag
  364.                         // QS FLAG IS NOT CLEARED INSIDE THIS ISR
  365.                 }                       
  366.         }

  367.         if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
  368.                 //    blinkPin=1;            // turn off pin 13 LED
  369.                 Pulse = false;                         // reset the Pulse flag so we can do it again
  370.                 amp = Peak - Trough;                           // get amplitude of the pulse wave
  371.                 thresh = amp/2 + Trough;                    // set thresh at 50% of the amplitude
  372.                 Peak = thresh;                            // reset these for next time
  373.                 Trough = thresh;
  374.         }

  375.         if (N > 2500){                           // if 2.5 seconds go by without a beat
  376.                 thresh = 512;                          // set thresh default
  377.                 Peak = 512;                               // set P default
  378.                 Trough = 512;                               // set T default
  379.                 lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
  380.                 firstBeat = true;                      // set these to avoid noise
  381.                 secondBeat = false;                    // when we get the heartbeat back
  382.         }

  383.         EA=1;                                   // enable interrupts when youre done!
  384. }// end isr


复制代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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