久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10477|回復: 9
打印 上一主題 下一主題
收起左側

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)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

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

使用道具 舉報

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

嗯,這里沒有使用蜂鳴器
回復

使用道具 舉報

地板
ID:663421 發表于 2019-12-13 18:00 | 只看該作者
學習一下,謝謝分享
回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

8#
ID:789460 發表于 2020-6-25 16:09 | 只看該作者
下載打不開
回復

使用道具 舉報

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

使用道具 舉報

10#
ID:850392 發表于 2020-12-1 19:43 | 只看該作者
沒有加入小數點的運算程序。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 天堂色 | 国产黄色小视频 | 亚洲一区二区精品视频在线观看 | 免费观看一区二区三区毛片 | 欧美激情精品久久久久 | 影音先锋中文字幕在线观看 | 亚洲高清视频一区 | 日韩欧美中文 | 综合精品 | 国产中文字幕av | 久久国产精品一区二区 | 欧美中文字幕一区二区三区亚洲 | 亚洲一区国产 | 国产精品精品视频一区二区三区 | 欧美一区二 | 美女视频网站久久 | 日韩一区二区在线视频 | 国产乱码久久久久久一区二区 | 欧美aⅴ | 欧美中文字幕一区二区三区亚洲 | 一区亚洲| 精品日韩一区 | 成人精品一区 | 欧美精品一区二区三区在线播放 | 噜啊噜在线 | 美日韩中文字幕 | 欧美一级毛片在线播放 | 久久久久久久一区 | 欧美精品久久 | 国产美女黄色 | 男人视频网站 | 欧美一级二级三级视频 | 免费黄色网址视频 | 午夜成人免费视频 | 91p在线观看 | 99国产精品久久久久久久 | 午夜精品福利视频 | 99久久99 | 日韩精品一区二区三区在线观看 | 91精品国产777在线观看 | 成人在线 |