找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于單片機(jī)的脈搏測量儀設(shè)計(jì)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:918467 發(fā)表于 2021-5-12 19:32 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
  1. #include <reg52.h>                 //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char  //無符號字符型 宏定義        變量范圍0~255
  3. #define uint  unsigned int         //無符號整型 宏定義        變量范圍0~65535
  4. #include <intrins.h>
  5. #include "eeprom52.h"

  6. sbit beep = P2^0;   //蜂鳴器IO口定義

  7. sbit k1 = P1^3;
  8. sbit k2 = P1^4;
  9. sbit k3 = P1^5;

  10. bit flag_300ms ;
  11. uchar flag_en;

  12. uchar code table_num[]="0123456789abcdefg";

  13. sbit rs=P1^0;         //寄存器選擇信號 H:數(shù)據(jù)寄存器          L:指令寄存器
  14. sbit rw=P1^1;         //寄存器選擇信號 H:數(shù)據(jù)寄存器          L:指令寄存器
  15. sbit e =P1^2;         //片選信號   下降沿觸發(fā)

  16. char flag=0,bj=90;
  17. unsigned char i=0,timecount=0,displayOK=0,aa=0;
  18. float time[6]={0};
  19. uint rate;

  20. float rate1[6];


  21. /***********************1ms延時(shí)函數(shù)*****************************/
  22. void delay_1ms(uint q)
  23. {
  24.         uint i,j;
  25.         for(i=0;i<q;i++)
  26.                 for(j=0;j<110;j++);
  27. }


  28. /********************************************************************
  29. * 名稱 : delay_uint()
  30. * 功能 : 小延時(shí)。
  31. * 輸入 : 無
  32. * 輸出 : 無
  33. ***********************************************************************/
  34. void delay_uint(uint q)
  35. {
  36.         while(q--);
  37. }

  38. /******************把數(shù)據(jù)保存到單片機(jī)內(nèi)部eeprom中******************/
  39. void write_eeprom()
  40. {
  41.         SectorErase(0x2000);
  42.         byte_write(0x2000, bj % 256);
  43.         byte_write(0x2001, bj / 256);
  44.         byte_write(0x2058, a_a);       
  45. }

  46. /******************把數(shù)據(jù)從單片機(jī)內(nèi)部eeprom中讀出來*****************/
  47. void read_eeprom()
  48. {
  49.         bj  = byte_read(0x2001);
  50.         bj<<= 8;
  51.         bj  |= byte_read(0x2000);
  52.         a_a      = byte_read(0x2058);
  53. }

  54. /**************開機(jī)自檢eeprom初始化*****************/
  55. void init_eeprom()
  56. {
  57.         read_eeprom();                //先讀
  58.         if(a_a != 1)                //新的單片機(jī)初始單片機(jī)內(nèi)問eeprom
  59.         {
  60.                 bj = 95;
  61.                 a_a = 1;
  62.                 write_eeprom();           //保存數(shù)據(jù)
  63.         }       
  64. }


  65. /********************************************************************
  66. * 名稱 : write_com(uchar com)
  67. * 功能 : 1602命令函數(shù)
  68. * 輸入 : 輸入的命令值
  69. * 輸出 : 無
  70. ***********************************************************************/
  71. void write_com(uchar com)
  72. {
  73.         e=0;
  74.         rs=0;
  75.         rw=0;
  76.         P0=com;
  77.         delay_uint(25);
  78.         e=1;
  79.         delay_uint(100);
  80.         e=0;
  81. }

  82. /********************************************************************
  83. * 名稱 : write_data(uchar dat)
  84. * 功能 : 1602寫數(shù)據(jù)函數(shù)
  85. * 輸入 : 需要寫入1602的數(shù)據(jù)
  86. * 輸出 : 無
  87. ***********************************************************************/
  88. void write_data(uchar dat)
  89. {
  90.         e=0;
  91.         rs=1;
  92.         rw=0;
  93.         P0=dat;
  94.         delay_uint(25);
  95.         e=1;
  96.         delay_uint(100);
  97.         e=0;       
  98. }

  99. /********************************************************************
  100. * 名稱 : write_string(uchar hang,uchar add,uchar *p)
  101. * 功能 : 改變液晶中某位的值,如果要讓第一行,第五個(gè)字符開始顯示"ab cd ef" ,調(diào)用該函數(shù)如下
  102.                   write_string(1,5,"ab cd ef;")
  103. * 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
  104. * 輸出 : 無
  105. ***********************************************************************/
  106. void write_string(uchar hang,uchar add,uchar *p)
  107. {
  108.         if(hang==1)   
  109.                 write_com(0x80+add);
  110.         else
  111.                 write_com(0x80+0x40+add);
  112.         while(1)
  113.         {
  114.                 if(*p == '\0')  break;
  115.                 write_data(*p);
  116.                 p++;
  117.         }       
  118. }

  119. /***********************lcd1602上顯示特定的字符************************/
  120. void write_zifu(uchar hang,uchar add,uchar date)
  121. {
  122.         if(hang==1)   
  123.                 write_com(0x80+add);
  124.         else
  125.                 write_com(0x80+0x40+add);
  126.         write_data(date);       
  127. }

  128. /***********************lcd1602上顯示兩位十進(jìn)制數(shù)************************/
  129. void write_sfm3(uchar hang,uchar add,uint date)
  130. {
  131.         if(hang==1)   
  132.                 write_com(0x80+add);
  133.         else
  134.                 write_com(0x80+0x40+add);
  135.         write_data(0x30+date/100%10);
  136.         write_data(0x30+date/10%10);
  137.         write_data(0x30+date%10);       
  138. }

  139. /***********************lcd1602上顯示兩位十進(jìn)制數(shù)************************/
  140. void write_sfm1(uchar hang,uchar add,uint date)
  141. {
  142.         if(hang==1)   
  143.                 write_com(0x80+add);
  144.         else
  145.                 write_com(0x80+0x40+add);
  146.         write_data(0x30+date%10);       
  147. }

  148. /***********************lcd1602初始化設(shè)置************************/
  149. void init_1602()
  150. {
  151.         write_com(0x38);        //設(shè)置顯示模式
  152.         write_com(0x0c);  //開顯示不顯示光標(biāo),光標(biāo)不閃爍
  153.         write_com(0x06);  //寫一個(gè)數(shù)據(jù),指針加1
  154.         delay_uint(1000);
  155.         write_string(1,0,"   Heart Rate     ");       
  156.         write_string(2,0,"     000/min       ");
  157. }

  158. /*************定時(shí)器0初始化程序***************/
  159. void time_init()          
  160. {
  161.         EA   = 1;                   //開總中斷
  162.         TMOD = 0X01;          //定時(shí)器0、定時(shí)器1工作方式1
  163.         ET0  = 1;                  //開定時(shí)器0中斷
  164.         TR0  = 1;                  //允許定時(shí)器0定時(shí)
  165. }


  166. /***********外部中斷0初始化程序****************/
  167. void init_int0()          //外部中斷0初始化程序
  168. {
  169.         EX0=1;                          //允許外部中斷0中斷
  170.         EA=1;                           //開總中斷
  171.         IT0 = 1;                   //外部中斷0負(fù)跳變中斷
  172. }

  173.        
  174. /************ 排序***************/
  175. void pingjun_zhi(float *p)
  176. {
  177.         static float value;
  178.         static uchar i,j;
  179.         for(j=1;j<5;j++)                   //先對整個(gè)數(shù)組的5個(gè)值進(jìn)行從小到大的排列
  180.                 for(i=0;i<5 - j;i++)
  181.                 {
  182.                         if(p[i] > p[i+1])
  183.                         {
  184.                                 value = p[i];
  185.                                 p[i] = p[i+1];
  186.                                 p[i+1] = value;               
  187.                         }       
  188.                 }
  189. }

  190. void key()
  191. {
  192.         if(k1==0)
  193.         {
  194.                 while(k1==0);
  195.                 flag++;
  196.                 if(flag==2){flag=0;write_eeprom();}
  197.                 if(flag==0)
  198.                 {
  199.                         write_string(1,0,"   Heart Rate   ");       
  200.                         write_string(2,0,"     000/min    ");               
  201.                 }
  202.                 if(flag==1)
  203.                 {
  204.                         write_string(1,0,"   set Rate     ");       
  205.                         write_string(2,0,"     000/min    ");               
  206.                 }
  207.         }
  208.         if(flag==1)
  209.         {
  210.                 if(k2==0)
  211.                 {
  212.                         while(k2==0);
  213.                         if(bj<99)bj++;
  214.                 }
  215.                 if(k3==0)
  216.                 {
  217.                         while(k3==0);
  218.                         if(bj>5) bj--;
  219.                 }
  220.         }
  221. }
  222. uchar flag_value;

  223. /****************主函數(shù)***************/
  224. void main()
  225. {       
  226.         beep = 0;                                //開機(jī)叫一聲   
  227.         delay_1ms(150);
  228.         P0 = P1 = P2 = P3 = 0xff;
  229.         init_1602();                    //1602初始化
  230.         time_init();                    //初始化定時(shí)器
  231.         init_int0();          //外部中斷0初始化程序
  232.         init_eeprom();
  233.         while(1)
  234.         {
  235.                 key();
  236.                 if(flag==0)
  237.                 {
  238.                         if(displayOK==0)//如果顯示關(guān)
  239.                         {
  240.                                  rate = 0;
  241.                                 flag_value = 0;
  242.                         }
  243.                         else//如果顯示開
  244.                         {
  245.                                 if(flag_en == 1)
  246.                                 {
  247.                                         flag_en = 0;
  248.                                         flag_value ++;
  249.                                         if(flag_value == 1)
  250.                                                 rate1[0]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
  251.                                         if(flag_value == 2)
  252.                                                 rate1[1]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
  253.                                         if(flag_value == 3)
  254.                                                 rate1[2]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
  255.                                         if(flag_value == 4)
  256.                                                 rate1[3]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
  257.                                         if(flag_value >= 5)
  258.                                         {
  259.                                                 rate1[4]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
  260.                                
  261.                                                 pingjun_zhi(rate1);
  262.                                                 flag_value = 0;
  263.                                                 rate = (rate1[1] / 3 + rate1[2] / 3 + rate1[3] / 3);
  264.                                         }
  265.                                 }
  266.                         }
  267.        
  268.                         write_sfm3(2,5,rate);
  269.                        
  270.                         if(rate>bj)beep=0;
  271.                         else beep=1;       
  272.                 }                       

  273.                 if(flag==1)
  274.                 {
  275.                         write_sfm3(2,5,bj);
  276.                 }


  277. //                write_sfm3(1,13,b1);
  278. //                write_sfm3(1,14,b2);
  279. //                write_sfm3(1,15,b3);
  280.                 delay_1ms(300);
  281.         }
  282. }
  283. /************外部0中斷服務(wù)程序***************/
  284. void int0() interrupt 0
  285. {
  286.         static uchar value;
  287.                 EX0=0;//暫時(shí)關(guān)外部中斷
  288.                 if(timecount<8)   //當(dāng)連續(xù)兩次檢測時(shí)間間隔小于8*50ms=400ms不處理
  289.                 {
  290.                         value ++;
  291.                         if(value >= 4)
  292.                         {
  293.                                 value = 0;
  294. //                                flag_value = 0;
  295.                         }       
  296.                         TR0=1;//開定時(shí)器
  297.                 }
  298.                 else if(timecount <= 18)
  299.                 {       
  300.                         value = 0;
  301.                         time[i]=timecount*50+TH0*0.256+TL0/1000;//算出間隔時(shí)間

  302.                         TH0 = 0x3c;
  303.                         TL0 = 0xb0;     // 50ms         12M
  304.                         timecount=0;//50ms計(jì)數(shù)清零
  305.                         i++;
  306.                         flag_en = 1;
  307.                         if(i==6)//記錄到超過等于6次時(shí)間
  308.                         {
  309.                                 i=1;//計(jì)數(shù)從1開始
  310.                                 displayOK=1;    //測得5次開始顯示?
  311.                         }                                                               
  312.                 } else
  313.                 {
  314.                         flag_value = 0;
  315.                         timecount = 0;
  316.                 }
  317.                 EX0=1;
  318. }
  319. /*************定時(shí)器0中斷服務(wù)程序***************/
  320. void time0_int() interrupt 1
  321. {       
  322.         TH0 = 0x3c;
  323.         TL0 = 0xb0;     // 50ms         12M
  324.         timecount++;//每50ms一次計(jì)數(shù)
  325.         if(timecount>70)     //當(dāng)超過25*50ms=1.5s沒有檢測到信號停止顯示
  326.         {
  327.                         i=0;//數(shù)據(jù)個(gè)數(shù)清零
  328.                         timecount=0;//50ms計(jì)數(shù)清零
  329.                         displayOK=0;//顯示關(guān)
  330.                         TR0=0;//定時(shí)器關(guān)
  331.                         TH0 = 0x3c;
  332.                         TL0 = 0xb0;     // 50ms         12M
  333.         }
  334. }
復(fù)制代碼

系統(tǒng)總體設(shè)計(jì)由STC89C52、按鍵、LCD1602、光電傳感器、時(shí)鐘模塊、運(yùn)放等構(gòu)成,系統(tǒng)設(shè)有四個(gè)按鍵,可以設(shè)置上下限脈搏數(shù),當(dāng)超過范圍的時(shí)候單片機(jī)會(huì)驅(qū)動(dòng)蜂鳴器發(fā)響,脈搏測量的時(shí)候需要人把手輕輕的按在光電傳感器上面,由于人脈搏跳動(dòng)的時(shí)候,血液的透光性不一樣會(huì)導(dǎo)致接收器那邊接收的信號強(qiáng)弱不一樣,間接的把人脈搏信號傳回,通過運(yùn)放對其進(jìn)行放大、整形后連接到單片機(jī)的IO口,單片機(jī)利用外部中斷對其進(jìn)行計(jì)數(shù),最終換算成人一分鐘脈搏的跳動(dòng)次數(shù),最終顯示在液晶屏上。

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

使用道具 舉報(bào)

沙發(fā)
ID:1144925 發(fā)表于 2025-4-15 13:48 | 只看該作者
eeprom52.h 文件有嗎
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

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

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