使用时把右手食指指肚放在st188反射式红外传感器上,放置合适时会看到指示灯随心跳同时闪动,如果没有闪烁请适当调节手指压力,调节完后在测试过程中手指压力不要变,保持稳定,当指示灯有规律闪烁时表示信号正确。当单片机检测到大约第五次信号时开始显示这五次信号算出的平均心率。当超过大约1.5秒没有检测到信号,清除心率。
如果手指抖动或者不稳定会看到指示灯乱闪,这样测得的数据不准,在测试过程中保持稳定!
1:初始化液晶和定时器
2:检测外部中断,并记录中断时间间隔
3:当有超过5个符合要求的时间记录,算出5个时间的平均值和对应的60s的心率并显示
4:当超过1.5s没有检测到中断发生停止显示
2-3-4循环
电路原理图如下:
单
片机源程序如下:
1. #include<reg52.h>
2. #define uint unsigned int
3. #define uchar unsigned char
4. sbit rs=P1^0; //数据与命令选择控制引脚
5. sbit rw=P1^1; //读与写选择控制引脚
6. sbit en=P1^2; //使能择控制引脚
7. sbit bf=P0^7; //忙标志位
8.
9. sbit P32=P3^2;
10.
11. unsigned char i=0,timecount=0,displayOK=0,rate=0,aa=0;
12. unsigned int time[6]={0};
13.
14. /************ 延时函数 *****************/
15. void delay(uint z)
16. {
17. while(z--);
18. }
19. /************ 忙检测函数 *****************/
20. void jiance()
21. {
22. P0=0xff;
23. rs=0;rw=1;en=1;
24. while(bf); //如果BF==1表示液晶在忙
25. en=0;
26. }
27. /************ 写命令函数 *****************/
28. void write_com(uchar com)
29. {
30. jiance();
31. P0=com;
32. rs=0;rw=0;en=1;
33. delay(2);
34. en=0;
35. }
36. /************ 写数据函数 *****************/
37. void write_dat(uchar dat)
38. {
39. jiance();
40. P0=dat;
41. rs=1;rw=0;en=1;
42. delay(2);
43. en=0;
44. }
45. /************ 1602液晶初始化函数 *****************/
46. void init_lcd()
47. {
48. write_com(0x38); // 设置16*2显示,5*7点阵,8位数据接口
49. write_com(0x0c); // 开显示,不显示光标
50. write_com(0x06); // 地址加1,当写入数据的时候光标右移
51. write_com(0x01); //清屏
52. }
53.
54. /******************************************************************/
55. /* 在指定位置写字符 */
56. /******************************************************************/
57. void LCD_write_char(unsigned char x,unsigned char y,unsigned char Data)
58. {
59. if (y == 0)
60. write_com(0x80 + x);
61. else
62. write_com(0xC0 + x);
63. write_dat(Data);
64. }
65. void DelayMs(unsigned int z)
66. {
67. unsigned int x;
68. for(;z>0;z--)
69. for(x=110;x>0;x--);
70. }
71. void main()
72. {
73. P32=1;
74. init_lcd();//lcd初始化
75. TCON=0x01;//设置外部中断0
76. EX0=1;
77. TMOD=0x01;//定时器0初始化
78. TH0=(65536-50000)/256;//实测每50ms中断的定时值
79. TL0=(65536-50000)%256;
80. ET0=1;//开定时器中断
81. //显示基本文字
82. LCD_write_char(3,0,'H');
83. LCD_write_char(4,0,'e');
84. LCD_write_char(5,0,'a');
85. LCD_write_char(6,0,'r');
86. LCD_write_char(7,0,'t');
87. LCD_write_char(8,0,' ');
88. LCD_write_char(9,0,'R');
89. LCD_write_char(10,0,'a');
90. LCD_write_char(11,0,'t');
91. LCD_write_char(12,0,'e');
92.
93. LCD_write_char(8,1,'/');
94. LCD_write_char(9,1,'m');
95. LCD_write_char(10,1,'i');
96. LCD_write_char(11,1,'n');
97. TR0=0;//定时器停止
98. EA=1;//开总中断
99. while(1)
100. {
101.
102. if(displayOK==1)
103. {
104. rate=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
105. LCD_write_char(5,1,rate/100+48);
106. LCD_write_char(6,1,(rate%100)/10+48);
107. LCD_write_char(7,1,rate%10+48);
108. }
109. DelayMs(300);
110. }
111. }
112.
113. void ex0() interrupt 0
114. {
115. EX0=0;//暂时关外部中断
116. if(timecount<8) //当连续两次检测时间间隔小于8*50ms=400ms不处理
117. {
118. TR0=1;//开定时器
119. }
120. else
121. {
122. time[i]=timecount*50+TH0*0.256+TL0/1000;//算出间隔时间
123. TL0=(65536-50000)%256;//重新设置定时器
124. TH0=(65536-50000)/256;
125. timecount=0;//50ms计数清零
126. i++;
127. if(i==6)//记录到超过等于6次时间
128. {
129. i=1;//计数从1开始
130. displayOK=1; //测得5次开始显示
131. }
132.
133. }
134. EX0=1;
135. }
136. void et0() interrupt 1
137. {
138. TL0=(65536-50000)%256;
139. TH0=(65536-50000)/256;
140.
141. timecount++;//每50ms一次计数
142. if(timecount>25) //当超过25*50ms=1.25s没有检测到信号停止显示
143. {
144. i=0;//数据个数清零
145. timecount=0;//50ms计数清零
146. displayOK=0;//显示关
147. TR0=0;//定时器关
148. TH0=(65536-50000)/256;
149. TL0=(65536-50000)%256;
150. }
151. }
152.