欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 51單片機實現簡單計算器C語言程序+Proteus仿真 [打印本頁]

作者: Kansa    時間: 2019-1-31 23:33
標題: 51單片機實現簡單計算器C語言程序+Proteus仿真
我們在這里使用4*4的矩陣按鍵KEYPAD-SMALLCALC與1602液晶屏LMO16L在單片機上實現簡單的計算器仿真實驗。
首先我們定義一個字符數組存儲按鍵對應的鍵值,使用程序查詢的方法掃描矩陣按鍵;當結束輸入時,我們就對字符串進行處理了并將結果顯示在液晶屏上。
在程序中,適當的使用一些庫函數可以大大提高我們的編程效率,在這里,我們主要對字符串進行操作,使用了stdlib.h、ctype.h庫中的一些函數,如下:
atoi:將字符串轉換成整數
atof:將字符串轉換成浮點數
isalnum:測試是否為字母數字


單片機源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>
  3. #include<ctype.h>
  4. #include<stdlib.h>
  5. #include<stdio.h>
  6. #include<math.h>
  7. #include<string.h>
  8. #define uchar unsigned char
  9. #define        uint unsigned int
  10. sbit LCDEN=P3^4;
  11. sbit RS=P3^5;
  12. sbit RW=P3^6;
  13. sbit BF=P0^7;
  14. sbit BEEP=P1^0;        
  15. uchar str[17];

  16. uchar code keyval[]="789/456*123-c0=+"; //按鍵對應的符號
  17. void delay(unsigned int xms)
  18. {
  19.         int i,j;
  20.         for(i=xms;i>0;i--)
  21.                 for(j=110;j>0;j--);
  22. }
  23. uchar keypad4_4()//按鍵掃描函數:要去抖,若有按鍵按下,返回對應的按鍵值(0-15),沒有按鍵按下返回16
  24. {
  25.         uchar i,row,temp;
  26.         uchar key=16;//按鍵號,初值設置為16,目的是:沒有按鍵按下時返回16;
  27.                   //若不設初值(默認值為0),沒有按鍵按下時,將返回0,會誤認為0被按下  
  28.         row=0xef; //從第一列開始      
  29.         for(i=0;i<4;i++)
  30.         {
  31.                 P2=0xff;  
  32.                 P2=row;        //第i列信號,對應列為低,其他全為高
  33.                 row=_crol_(row,1);           //生成下一列信號
  34.                 temp=P2; //讀入掃描信號
  35.                 temp=temp&0x0f; //屏蔽高4位列信號,只保留低4位行信號
  36.                 if(temp!=0x0f)//有按鍵被按下,因為第i列某行有按鍵按下,則低4位中有一位為低  
  37.                  {  
  38.                         delay(20);  //延時去抖
  39.                         temp=P2;  
  40.                         temp=temp&0x0f;  
  41.                         if(temp!=0x0f)   //再次確認有按鍵被按下
  42.                           {  
  43.                         switch(temp)  //根據低4位行信號,判斷哪個按鍵被按下
  44.                     {  
  45.                             case 0x0e:key=0+i;break; //第i列第1行按鍵被按下
  46.                         case 0x0d:key=4+i;break; //第i列第2行按鍵被按下  
  47.                         case 0x0b:key=8+i;break; //第i列第3行按鍵被按下
  48.                                         case 0x07:key=12+i;      //第i列第4行按鍵被按下
  49.                     }
  50.                                 
  51.                                 do
  52.                                 {
  53.                                         temp=P2;              //再次掃描按鍵
  54.                                           temp=temp&0x0f;  
  55.                                   }while(temp!=0x0f); //等待按鍵釋放   
  56.                           }  
  57.              }
  58.         }  
  59.         return(key);//掃面結束,返回按鍵值
  60. }

  61. uchar RdACAdr()//讀當前光標地址
  62. {   
  63.         uchar result;
  64.         P2 = 0xff;        //讀地址前先置高電平,防止誤判
  65.         RS = 0;
  66.         delay(5);
  67.     RW = 1;
  68.         LCDEN = 1;
  69.         delay(5);
  70.         result=P2&0x7f; //去掉最高位忙閑標記,只保留低7位地址值
  71.         LCDEN = 0;
  72.         return result;                     
  73. }

  74. uchar DectectBusyBit(void)//狀態判斷函數(忙/閑?)
  75. {   
  76.         bit result;
  77.         P0 = 0xff;        //讀狀態前先置高電平,防止誤判
  78.         RS = 0;
  79.         delay(5);
  80.     RW = 1;
  81.         LCDEN = 1;
  82.         delay(5);
  83.         result=BF; //若LCM忙,則反復測試,在此處原地踏步;當LCM閑時,才往下繼續
  84.         LCDEN = 0;
  85.         return result;                     
  86. }

  87. void WrComLCD(unsigned char ComVal)//寫命令函數
  88. {
  89.         while(DectectBusyBit()==1);         //先檢測LCM是否空閑
  90.         RS = 0;
  91.         delay(1);
  92.     RW = 0;
  93.         LCDEN = 1;
  94.         P0 = ComVal;
  95.         delay(1);
  96.         LCDEN = 0;        
  97. }

  98. void WrDatLCD(uchar DatVal)//寫數據函數
  99. {
  100.         while(DectectBusyBit()==1);
  101.         RS = 1;
  102.         delay(1);
  103.     RW = 0;
  104.         LCDEN = 1;
  105.         P0 = DatVal;
  106.         delay(1);
  107.         LCDEN = 0;        
  108. }
  109. void WrStrDat(uchar *p)//顯示英文字符串(長度不超過32)
  110. {        
  111.         uchar i=0,t;
  112.    
  113.         while(p[i]!='\0')
  114.         {  
  115.                   WrDatLCD(p[i]);
  116.                 i++;
  117.                 delay(5);
  118.         
  119.                 t=RdACAdr();
  120.         if(t==0x10) WrComLCD(0xc0);//讀當前坐標,如果第1行寫完換行到第2行        
  121.                 if(t==0x50) WrComLCD(0x80);//讀當前坐標,如果第2行寫完換行到第1行        
  122.         }        
  123. }

  124. void LCD_Init(void)//1602初始化函數
  125. {
  126.         //delay(15);
  127.         WrComLCD(0x38);
  128.         //delay(5);     // 功能設定:16*2行、5*7點陣、8位數據接口
  129.         WrComLCD(0x38);
  130.         //delay(5);
  131.         WrComLCD(0x38);   
  132. //多次重復設定功能指令,因為LCD啟動后并不知道使用的是4位數據接口還是8位的,所以開始時總是默認為4位,這樣剛開始寫入功能設定指令時,低4位被忽略,為了可靠,最好多寫幾遍該指令
  133.         WrComLCD(0x01);    // 清屏
  134.         WrComLCD(0x06);    // 光標自增、屏幕不動  
  135.         delay(1);              // 延時,等待上面的指令生效,下面再顯示,防止出現亂碼
  136.         WrComLCD(0x0C);    // 開顯示、關光標
  137. }
  138. double str2num(uchar* str)
  139. {
  140.         uint i=0,j=0,index=0;
  141.         uchar ch[10];
  142.         long a1=atol(str),b1=0;
  143.         double a2=atof(str),b2=0,c=0;
  144.         for(i=0;str[i]!='\0';i++)
  145.         {
  146.                 if(!isalnum(str[i]))
  147.                 {
  148.                         index=i;
  149.                         break;
  150.                 }
  151.         }
  152.         for(j=0,i=index+1;i<=strlen(str);i++)
  153.                 ch[j++]=str[i];
  154.         b1=atol(ch);
  155.         b2=atof(ch);
  156.         switch(str[index])
  157.         {
  158.                 case '+':c=a1+b1;break;
  159.                 case '-':c=a1-b1;break;
  160.                 case '*':c=a2*b2;break;
  161.                 case '/':c=a2/b2;break;
  162.                 default:c=a2;break;
  163.         }
  164.         return c;
  165. }
  166. void main()
  167. {
  168.         
  169.         uchar i=0,j=0,y=16;
  170.         uchar flag=0;
  171.         uchar end=0;        
  172.         LCD_Init();
  173.         delay(5);   //延時,等待初始化完成
  174.         WrComLCD(0x80);           //設置顯示地址第一行第一位:0X00(0x80+0x00)  
  175.         delay(1);
  176.            WrComLCD(0xc0);
  177.         delay(1);
  178.         WrDatLCD('0');
  179.         delay(1);
  180.         WrComLCD(0x80);
  181.         while(1)
  182.         {        
  183.                 y=keypad4_4();
  184.                                 
  185.                 if(y<16)
  186.                 {        
  187.                         if(y!=12)
  188.                         {
  189.                                 if(end==1)
  190.                                 {
  191.                                         end=0;
  192.                                         flag=0;
  193.                                         WrComLCD(0x01);         
  194.                                         delay(1);
  195.                                         WrComLCD(0xc0);
  196.                                         delay(1);
  197.                                         WrDatLCD('0');
  198.                                         delay(1);        
  199.                                         WrComLCD(0x80);        
  200.                                 }                  
  201.                                 str[strlen(str)]=keyval[y];
  202.                                 WrDatLCD(keyval[y]);
  203.                                 if(y==14)
  204.                                 {
  205.                                         uchar ch[17];
  206.                                         flag=1;
  207.                                         end=1;
  208.                                         str[strlen(str)]='\0';
  209.                                         WrComLCD(0xc0);
  210.                                                 
  211.                                         sprintf(ch,"%.2f",str2num(str));
  212.                                         WrStrDat(ch);
  213.                                         for(i=0;i<17;i++)
  214.                                                 str[i]='\0';
  215.                                 }
  216.                         }
  217.                         else
  218.                         {
  219. ……………………

  220. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
51簡單計算器.zip (141.66 KB, 下載次數: 159)

作者: GameGhost96    時間: 2019-3-7 16:54
蜂鳴器沒有作用,似乎缺失蜂鳴器功能部分的程序。
作者: Kansa    時間: 2019-5-19 17:45
GameGhost96 發表于 2019-3-7 16:54
蜂鳴器沒有作用,似乎缺失蜂鳴器功能部分的程序。

嗯,這里沒有使用蜂鳴器
作者: lzj527095842    時間: 2019-12-13 18:00
學習一下,謝謝分享

作者: hasakei    時間: 2020-6-23 11:33
多謝,研究一下。
作者: hasakei    時間: 2020-6-23 11:36
多謝,研究一下。
作者: hasakei    時間: 2020-6-23 21:04
好用,多謝分享。
作者: 1479558579    時間: 2020-6-25 16:09
下載打不開
作者: lgs8317    時間: 2020-11-15 14:14
找了很久用于學習的程序,謝謝,但愿能下載,
作者: 15219584771    時間: 2020-12-1 19:43
沒有加入小數點的運算程序。





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