找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

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

51單片機(jī)實(shí)現(xiàn)簡(jiǎn)單計(jì)算器C語(yǔ)言程序+Proteus仿真

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
我們?cè)谶@里使用4*4的矩陣按鍵KEYPAD-SMALLCALC與1602液晶屏LMO16L在單片機(jī)上實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器仿真實(shí)驗(yàn)。
首先我們定義一個(gè)字符數(shù)組存儲(chǔ)按鍵對(duì)應(yīng)的鍵值,使用程序查詢的方法掃描矩陣按鍵;當(dāng)結(jié)束輸入時(shí),我們就對(duì)字符串進(jìn)行處理了并將結(jié)果顯示在液晶屏上。
在程序中,適當(dāng)?shù)氖褂靡恍⿴?kù)函數(shù)可以大大提高我們的編程效率,在這里,我們主要對(duì)字符串進(jìn)行操作,使用了stdlib.h、ctype.h庫(kù)中的一些函數(shù),如下:
atoi:將字符串轉(zhuǎn)換成整數(shù)
atof:將字符串轉(zhuǎn)換成浮點(diǎn)數(shù)
isalnum:測(cè)試是否為字母數(shù)字


單片機(jī)源程序如下:
  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=+"; //按鍵對(duì)應(yīng)的符號(hào)
  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()//按鍵掃描函數(shù):要去抖,若有按鍵按下,返回對(duì)應(yīng)的按鍵值(0-15),沒(méi)有按鍵按下返回16
  24. {
  25.         uchar i,row,temp;
  26.         uchar key=16;//按鍵號(hào),初值設(shè)置為16,目的是:沒(méi)有按鍵按下時(shí)返回16;
  27.                   //若不設(shè)初值(默認(rèn)值為0),沒(méi)有按鍵按下時(shí),將返回0,會(huì)誤認(rèn)為0被按下  
  28.         row=0xef; //從第一列開(kāi)始      
  29.         for(i=0;i<4;i++)
  30.         {
  31.                 P2=0xff;  
  32.                 P2=row;        //第i列信號(hào),對(duì)應(yīng)列為低,其他全為高
  33.                 row=_crol_(row,1);           //生成下一列信號(hào)
  34.                 temp=P2; //讀入掃描信號(hào)
  35.                 temp=temp&0x0f; //屏蔽高4位列信號(hào),只保留低4位行信號(hào)
  36.                 if(temp!=0x0f)//有按鍵被按下,因?yàn)榈趇列某行有按鍵按下,則低4位中有一位為低  
  37.                  {  
  38.                         delay(20);  //延時(shí)去抖
  39.                         temp=P2;  
  40.                         temp=temp&0x0f;  
  41.                         if(temp!=0x0f)   //再次確認(rèn)有按鍵被按下
  42.                           {  
  43.                         switch(temp)  //根據(jù)低4位行信號(hào),判斷哪個(gè)按鍵被按下
  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);//掃面結(jié)束,返回按鍵值
  60. }

  61. uchar RdACAdr()//讀當(dāng)前光標(biāo)地址
  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; //去掉最高位忙閑標(biāo)記,只保留低7位地址值
  71.         LCDEN = 0;
  72.         return result;                     
  73. }

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

  87. void WrComLCD(unsigned char ComVal)//寫(xiě)命令函數(shù)
  88. {
  89.         while(DectectBusyBit()==1);         //先檢測(cè)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)//寫(xiě)數(shù)據(jù)函數(shù)
  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)//顯示英文字符串(長(zhǎng)度不超過(guò)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);//讀當(dāng)前坐標(biāo),如果第1行寫(xiě)完換行到第2行        
  121.                 if(t==0x50) WrComLCD(0x80);//讀當(dāng)前坐標(biāo),如果第2行寫(xiě)完換行到第1行        
  122.         }        
  123. }

  124. void LCD_Init(void)//1602初始化函數(shù)
  125. {
  126.         //delay(15);
  127.         WrComLCD(0x38);
  128.         //delay(5);     // 功能設(shè)定:16*2行、5*7點(diǎn)陣、8位數(shù)據(jù)接口
  129.         WrComLCD(0x38);
  130.         //delay(5);
  131.         WrComLCD(0x38);   
  132. //多次重復(fù)設(shè)定功能指令,因?yàn)長(zhǎng)CD啟動(dòng)后并不知道使用的是4位數(shù)據(jù)接口還是8位的,所以開(kāi)始時(shí)總是默認(rèn)為4位,這樣剛開(kāi)始寫(xiě)入功能設(shè)定指令時(shí),低4位被忽略,為了可靠,最好多寫(xiě)幾遍該指令
  133.         WrComLCD(0x01);    // 清屏
  134.         WrComLCD(0x06);    // 光標(biāo)自增、屏幕不動(dòng)  
  135.         delay(1);              // 延時(shí),等待上面的指令生效,下面再顯示,防止出現(xiàn)亂碼
  136.         WrComLCD(0x0C);    // 開(kāi)顯示、關(guān)光標(biāo)
  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);   //延時(shí),等待初始化完成
  174.         WrComLCD(0x80);           //設(shè)置顯示地址第一行第一位: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. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
51簡(jiǎn)單計(jì)算器.zip (141.66 KB, 下載次數(shù): 159)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:432453 發(fā)表于 2019-3-7 16:54 | 只看該作者
蜂鳴器沒(méi)有作用,似乎缺失蜂鳴器功能部分的程序。
回復(fù)

使用道具 舉報(bào)

板凳
ID:404722 發(fā)表于 2019-5-19 17:45 | 只看該作者
GameGhost96 發(fā)表于 2019-3-7 16:54
蜂鳴器沒(méi)有作用,似乎缺失蜂鳴器功能部分的程序。

嗯,這里沒(méi)有使用蜂鳴器
回復(fù)

使用道具 舉報(bào)

地板
ID:663421 發(fā)表于 2019-12-13 18:00 | 只看該作者
學(xué)習(xí)一下,謝謝分享
回復(fù)

使用道具 舉報(bào)

5#
ID:786505 發(fā)表于 2020-6-23 11:33 | 只看該作者
多謝,研究一下。
回復(fù)

使用道具 舉報(bào)

6#
ID:786505 發(fā)表于 2020-6-23 11:36 | 只看該作者
多謝,研究一下。
回復(fù)

使用道具 舉報(bào)

7#
ID:786505 發(fā)表于 2020-6-23 21:04 | 只看該作者
好用,多謝分享。
回復(fù)

使用道具 舉報(bào)

8#
ID:789460 發(fā)表于 2020-6-25 16:09 | 只看該作者
下載打不開(kāi)
回復(fù)

使用道具 舉報(bào)

9#
ID:406255 發(fā)表于 2020-11-15 14:14 | 只看該作者
找了很久用于學(xué)習(xí)的程序,謝謝,但愿能下載,
回復(fù)

使用道具 舉報(bào)

10#
ID:850392 發(fā)表于 2020-12-1 19:43 | 只看該作者
沒(méi)有加入小數(shù)點(diǎn)的運(yùn)算程序。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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