標(biāo)題: 單片機(jī)設(shè)計(jì)求助,現(xiàn)在lcd顯示脈搏特別奇怪,數(shù)字特別小,特別容易報(bào)警? [打印本頁(yè)]

作者: cq995    時(shí)間: 2023-5-12 16:57
標(biāo)題: 單片機(jī)設(shè)計(jì)求助,現(xiàn)在lcd顯示脈搏特別奇怪,數(shù)字特別小,特別容易報(bào)警?


單片機(jī)源程序如下:
  1. #include <reg52.h>             //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char  //無(wú)符號(hào)字符型 宏定義    變量范圍0~255
  3. #define uint  unsigned int     //無(wú)符號(hào)整型 宏定義    變量范圍0~65535

  4. uchar menu_1;           //設(shè)置不同報(bào)警參數(shù)的變量
  5. uchar flag_200ms ;        //200毫秒的變量

  6. unsigned char i=0,rate=0,timecount=0;
  7. unsigned int time[6]={0};
  8. uchar rate_l=2,rate_h=200;   //脈搏上下限報(bào)警值

  9. sbit rs=P1^0;     //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器      L:指令寄存器
  10. sbit rw=P1^1;     //寄存器選擇信號(hào) H:數(shù)據(jù)寄存器      L:指令寄存器
  11. sbit e =P1^2;     //片選信號(hào)   下降沿觸發(fā)
  12. sbit beep = P3^7;       //蜂鳴器IO口定義,仿真
  13. sbit key1 = P3^6;        //按鍵IO口定義,仿真
  14. sbit key2 = P3^5;        //按鍵IO口定義,仿真
  15. sbit key3 = P3^4;        //按鍵IO口定義,仿真

  16. /***********************1ms延時(shí)函數(shù)*****************************/
  17. void delay_1ms(uint q)
  18. {
  19.     uint i,j;
  20.     for(i=0;i<q;i++)
  21.         for(j=0;j<120;j++);
  22. }

  23. /********************************************************************
  24. * 名稱(chēng) : delay_uint()
  25. * 功能 : 小延時(shí)。
  26. * 輸入 : 無(wú)
  27. * 輸出 : 無(wú)
  28. ***********************************************************************/
  29. void delay_uint(uint q)
  30. {
  31.     while(q--);
  32. }

  33. /********************************************************************
  34. * 名稱(chēng) : write_com(uchar com)
  35. * 功能 : 1602指令函數(shù)
  36. * 輸入 : 輸入的指令值
  37. * 輸出 : 無(wú)
  38. ***********************************************************************/
  39. void write_com(uchar com)
  40. {
  41.      rs=0;         //寫(xiě)指令
  42.     rw=0;         //對(duì)1602寫(xiě)操作
  43.     P0=com;         //P0口對(duì)1602寫(xiě)指令
  44.     delay_uint(25);
  45.     e=1;         //e=1使能信號(hào)
  46.     delay_uint(100);   //延時(shí)一下等1602完成操作
  47.     e=0;
  48. }

  49. /********************************************************************
  50. * 名稱(chēng) : write_data(uchar dat)
  51. * 功能 : 1602寫(xiě)數(shù)據(jù)函數(shù)
  52. * 輸入 : 需要寫(xiě)入1602的數(shù)據(jù)
  53. * 輸出 : 無(wú)
  54. ***********************************************************************/
  55. void write_data(uchar dat)
  56. {
  57.      rs=1;         //寫(xiě)數(shù)據(jù)
  58.     rw=0;         //對(duì)1602寫(xiě)操作
  59.     P0=dat;          //P0口對(duì)1602寫(xiě)數(shù)據(jù)
  60.     delay_uint(25);
  61.     e=1;         //e=1使能信號(hào)
  62.     delay_uint(100);   //延時(shí)一下等1602完成操作
  63.     e=0;   
  64. }

  65. /********************************************************************
  66. * 名稱(chēng) : write_string(uchar hang,uchar add,uchar *p)
  67. * 功能 : 改變液晶中某位的值,如果要讓第一行,第五個(gè)字符開(kāi)始顯示"ab cd ef" ,調(diào)用該函數(shù)如下
  68.           write_string(1,5,"ab cd ef;")
  69. * 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
  70. * 輸出 : 無(wú)
  71. ***********************************************************************/
  72. void write_string(uchar hang,uchar add,uchar *p)
  73. {
  74.     if(hang==1)   
  75.         write_com(0x80+add);       //寫(xiě)1602第一行的地址
  76.     else
  77.         write_com(0x80+0x40+add);   //寫(xiě)1602第二行的地址
  78.     while(1)                                                         
  79.     {
  80.         if(*p == '\0')  break;    //\0字符串的結(jié)尾標(biāo)志  break結(jié)束while循環(huán) 結(jié)束寫(xiě)字符
  81.         write_data(*p);        //寫(xiě)數(shù)據(jù)
  82.         p++;                //指針地址加1  
  83.     }   
  84. }

  85. /*****************控制光標(biāo)函數(shù)********************/
  86. void write_guanbiao(uchar hang,uchar add,uchar date)
  87. {        
  88.     if(hang==1)   
  89.         write_com(0x80+add);
  90.     else
  91.         write_com(0x80+0x40+add);
  92.     if(date == 1)
  93.         write_com(0x0f);     //顯示光標(biāo)并且閃爍   
  94.     else
  95.         write_com(0x0c);   //關(guān)閉光標(biāo)
  96. }   

  97. /***********************lcd1602上顯示3位十進(jìn)制數(shù)************************/
  98. void write_lcd3(uchar hang,uchar add,uint date)
  99. {
  100.     if(hang==1)   
  101.         write_com(0x80+add);       //寫(xiě)1602第一行的地址
  102.     else
  103.         write_com(0x80+0x40+add);  //寫(xiě)1602第二行的地址
  104.     write_data(0x30+date/100%10);    //顯示百位數(shù),加0x30轉(zhuǎn)換為ASCII字符
  105.     write_data(0x30+date/10%10);    //顯示十位數(shù)
  106.     write_data(0x30+date%10);       //顯示個(gè)位數(shù)   
  107. }

  108. /***********************lcd1602初始化設(shè)置************************/
  109. void init_1602()
  110. {
  111.     write_com(0x38);  //顯示模式設(shè)置:16×2顯示,5×7點(diǎn)陣,8位數(shù)據(jù)接口 不檢測(cè)忙信號(hào)
  112.     write_com(0x0c);  //開(kāi)顯示 不顯示光標(biāo)
  113.     write_com(0x06);  //當(dāng)寫(xiě)一個(gè)字符是,地址指針加 1
  114.     write_string(1,0,"    000/min    ");      //初始化1602顯示
  115.     write_string(2,0,"  H:000  L:000  ");      //初始化1602顯示
  116.     write_lcd3(2,4,rate_h);           
  117.     write_lcd3(2,11,rate_l);
  118. }

  119. /*************定時(shí)器0初始化程序***************/
  120. void time_init()      
  121. {
  122.     EA   = 1;           //開(kāi)總中斷
  123.     TMOD = 0X01;      //定時(shí)器0工作方式1
  124.     ET0  = 1;          //開(kāi)定時(shí)器0中斷
  125.     TR0  = 1;          //允許定時(shí)器0定時(shí)
  126. }

  127. /***********外部中斷0初始化程序****************/
  128. void init_int0()      //外部中斷0初始化程序
  129. {
  130.     EX0=1;              //允許外部中斷0中斷
  131.     EA=1;               //開(kāi)總中斷
  132.     IT0 = 1;           //外部中斷0負(fù)跳變中斷
  133. }
  134.   
  135. /********************獨(dú)立按鍵程序*****************/
  136. uchar key_can;     //按鍵值

  137. void key()     //獨(dú)立按鍵程序
  138. {
  139.     static uchar key_new;        //key_new  這個(gè)變量的功能是做按鍵松手檢測(cè)的
  140.     key_can = 0;                //按鍵值還原成0
  141.      if(key1 == 0 || key2 == 0 || key3 == 0)        //有按鍵按下
  142.     {
  143.         delay_1ms(1);             //按鍵延時(shí)消抖動(dòng)
  144.         if(key_new == 1)
  145.         {                     
  146.             key_new = 0;        //key_new = 0   說(shuō)明按鍵已按下
  147.             if(key1 == 0)        //確認(rèn)是按鍵按下
  148.                 key_can = 1;     //得到按鍵值
  149.             if(key2 == 0)        //確認(rèn)是按鍵按下
  150.                 key_can = 2;     //得到按鍵值
  151.             if(key3 == 0)        //確認(rèn)是按鍵按下
  152.                 key_can = 3;     //得到按鍵值
  153.         }            
  154.     }
  155.     else
  156.         key_new = 1;     //key_new = 1   說(shuō)明按鍵已經(jīng)松開(kāi)了   
  157. }

  158. /**********************設(shè)置函數(shù)************************/
  159. void key_with()
  160. {
  161.     if(key_can == 1)    //設(shè)置鍵
  162.     {
  163.         menu_1++;
  164.         if(menu_1 > 2)   
  165.         {
  166.             menu_1 = 0;          //menu_1 = 0 退出設(shè)置了,在正常顯示界面下
  167.             init_1602();      //初始化液晶顯示
  168.         
  169.         }
  170.     }
  171. /***************設(shè)置*********************/
  172.     if(menu_1 != 0)
  173.     {
  174.         if(menu_1 == 1)          //設(shè)置脈搏上限報(bào)警值
  175.         {
  176.             if(key_can == 2)    //加鍵
  177.             {
  178.                 rate_h ++;           //設(shè)置脈搏上限報(bào)警值 加1
  179.                 if(rate_h >= 255)
  180.                     rate_h = 0;
  181.             }        
  182.             if(key_can == 3)    //減鍵      
  183.             {
  184.                 rate_h -- ;           //設(shè)置脈搏上限報(bào)警值 減1
  185.                 if(rate_h <= rate_l)
  186.                     rate_h = rate_l + 1;    //限制脈搏上限不能低于脈搏下限
  187.             }   
  188.         }
  189.         if(menu_1 == 2)          //設(shè)置脈搏下限報(bào)警值
  190.         {
  191.             if(key_can == 2)    //加鍵
  192.             {
  193.                 rate_l ++;                   //設(shè)置脈搏下限報(bào)警值 加1
  194.                 if(rate_l >= rate_h)
  195.                     rate_l = rate_h - 1;   //限制脈搏下限不能高于脈搏上限
  196.             }   
  197.             if(key_can == 3)    //減鍵      
  198.             {
  199.                 if(rate_l == 0)
  200.                     rate_l = 1;
  201.                 rate_l -- ;                  //設(shè)置脈搏下限報(bào)警值 減1
  202.             }
  203.         }
  204.         write_lcd3(2,4,rate_h);               //顯示上限報(bào)警值
  205.         write_lcd3(2,11,rate_l);        //顯示下限報(bào)警值
  206.         delay_1ms(10);   
  207.     }
  208. }

  209. /****************報(bào)警函數(shù)***************/
  210. void clock_h_l()
  211. {
  212.     if(rate != 0)
  213.     {
  214.         if((rate <= rate_l) || (rate >= rate_h))
  215.         {
  216.             beep = ~beep;       //蜂鳴器報(bào)警            
  217.         }
  218.         else
  219.         {
  220.             beep = 1;    //取消報(bào)警
  221.         }
  222.     }else
  223.     {
  224.         beep = 1;   //取消報(bào)警   
  225.     }
  226.             
  227. }

  228. /****************主函數(shù)***************/
  229. void main()
  230. {   


  231.     init_1602();                    //1602初始化
  232.     time_init();                    //初始化定時(shí)器
  233.     init_int0();      //外部中斷0初始化程序
  234.     while(1)
  235.     {            
  236.         key();                     //按鍵函數(shù)
  237.          key_with();                 //按鍵設(shè)置函數(shù)
  238.           rate=60000/(time[1]+time[2]+time[3]+time[4]+time[5])/5;      //計(jì)算脈搏次數(shù)
  239.             write_lcd3(1,5,rate);     //顯示脈搏
  240.             clock_h_l();             //報(bào)警函數(shù)
  241.         delay_1ms(1);          //延時(shí)1毫秒
  242.     }
  243. }

  244. void int0() interrupt 0         //外部中斷0,由P3.2端口引入,低電平或下降沿引起
  245. {
  246.     if(timecount<8)   //當(dāng)連續(xù)兩次檢測(cè)時(shí)間間隔小于8*50ms=400ms不處理
  247.         {
  248.            TR0=1;//開(kāi)定時(shí)器
  249.         }
  250.     else
  251.     {
  252.          time[i]=timecount*50+TH0+TL0;//算出間隔時(shí)間,timecount是50ms計(jì)數(shù),每隔50ms timecount加1
  253. //         time[i]=timecount*50+TH0*0.256+TL0/1000;
  254. //         time[i]=TH0*256+TL0;
  255.          TH0 = 0x3c;
  256.          TL0 = 0xb0;     // 50ms         12M
  257.          timecount=0;//50ms計(jì)數(shù)清零
  258.           i++;
  259.         if(i==6)//記錄到超過(guò)等于6次時(shí)間
  260.         {
  261.             i=1;//計(jì)數(shù)從1開(kāi)始
  262.         }
  263.     }                                
  264. }


  265. void time0_int() interrupt 1
  266. {        
  267.         TH0 = 0x3c;
  268.         TL0 = 0xb0;     // 50ms         12M
  269.         timecount++;//每50ms一次計(jì)數(shù)
  270.         if(timecount>25)     //當(dāng)超過(guò)25*50ms=1.5s沒(méi)有檢測(cè)到信號(hào)停止顯示
  271.         {
  272.             i=0;//數(shù)據(jù)個(gè)數(shù)清零
  273.             timecount=0;//50ms計(jì)數(shù)清零
  274.             TR0=0;//定時(shí)器關(guān)
  275.             TH0 = 0x3c;
  276.             TL0 = 0xb0;     // 50ms         12M
  277.         }
  278. }
復(fù)制代碼





歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1