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

QQ登錄

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

帖子
查看: 15776|回復(fù): 23
收起左側(cè)

基于89c52的簡(jiǎn)易計(jì)算器設(shè)計(jì)(仿真與源程序)

  [復(fù)制鏈接]
ID:103952 發(fā)表于 2016-4-28 10:39 | 顯示全部樓層 |閱讀模式
最近在學(xué)習(xí)單片機(jī),把自己的資料分享給有需要的童鞋。

捕獲.PNG
51hei.png

源碼:(部分預(yù)覽 完整代碼請(qǐng)下載附件): 計(jì)算器設(shè)計(jì).7z (384.54 KB, 下載次數(shù): 410)
  1. #include<reg52.h>
  2. #include<math.h>
  3. #include "lcd1602_8.h"
  4. uint temp,num;//鍵盤(pán)掃描數(shù)值
  5. uchar keynum1=0,keynum2=0,sign=0,i=0,j=0; //按鍵計(jì)數(shù),符號(hào)標(biāo)示
  6. uchar num1[8]={0},num2[8]={0};         //按鍵存儲(chǔ)數(shù)組
  7. float ans1=0,ans2=0,ans=0,point=0; //運(yùn)算數(shù)據(jù)
  8. bit conflag=0;         //繼續(xù)運(yùn)算標(biāo)志位
  9. bit newcalc=0;        //新運(yùn)算標(biāo)志
  10. bit ac=0;                //清零標(biāo)志,1為清零
  11. bit beepflag=0;         //蜂鳴器標(biāo)志位
  12. bit sqrtflag1=0;        //開(kāi)方1標(biāo)志位
  13. bit sqrtflag2=0;        //開(kāi)方2標(biāo)志位
  14. bit        powflag=0;
  15. sbit keybeep=P3^3;//蜂鳴器開(kāi)關(guān)按鍵
  16. sbit beep=P2^3;         //蜂鳴器控制口
  17. sbit keysqrt=P3^4;//開(kāi)方按鍵
  18. sbit keypow=P3^5;//任意次方按鍵
  19. uchar keyscan();
  20. void maininit(void);
  21. /****主程序***/
  22. void main(void)
  23. {
  24.         maininit();//初始化
  25.         while(1)        //整個(gè)系統(tǒng)大循環(huán),讓計(jì)算器一直處于工作狀態(tài)
  26.         {
  27.                 while(1)        //第一運(yùn)算數(shù)掃描
  28.                 {
  29.                         if(ac==1)
  30.                                 break;         //若清零,則退出輸入
  31.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.')) //記錄按下的數(shù)字
  32.                         {
  33.                                 if(newcalc==1)          //新一次運(yùn)算開(kāi)始
  34.                                 {
  35.                                         lcdwrite_com(0x01);//清屏
  36.                                         newcalc=0;
  37.                                         lcd_setxy(0,0);
  38.                                 }
  39.                                 if(keynum1<=7)           //限制輸入位數(shù)
  40.                                 {                        
  41.                                         if(num=='.')
  42.                                         {        
  43.                                                 lcdwrite_data('.');        //顯示小數(shù)點(diǎn)
  44.                                         }
  45.                                         else
  46.                                                 lcdwrite_num1(num);
  47.                                         num1[keynum1]=num;
  48.                                         keynum1++;
  49.                                 }
  50.                         }
  51.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='='||num=='^'||keysqrt==0)  
  52.                         {
  53.                                 if(keynum1==0&&num1[0]==0)          //若直接輸入運(yùn)算符而沒(méi)有輸入數(shù)字則執(zhí)行連續(xù)運(yùn)算
  54.                                 {        
  55.                         here:        ans1=ans;
  56.                                         sign=num;
  57.                                         lcdwrite_com(0x01);
  58.                                         delayms(5);
  59.                                         lcd_setxy(0,0);
  60.                                         lcdwrite_float(ans1);
  61.                                         if(sqrtflag2!=1&&num!='N')
  62.                                                 lcdwrite_data(num);
  63.                                         break;
  64.                                 }
  65.                                 for(i=0;keynum1>0;i++)           //計(jì)算按下的數(shù)字的大小
  66.                                 {
  67.                                         if(num1[i]!='.')
  68.                                                 ans1=ans1*10+num1[i];
  69.                                         else if(num1[i]=='.')
  70.                                                 break;
  71.                                         keynum1--;
  72.                                 }
  73.                                 for(keynum1--,i++,j=0;keynum1>0;j++,i++,keynum1--)
  74.                                         point=point*10+num1[i];
  75.                                 for(;j>0;j--)
  76.                                         point*=0.1;
  77.                                 ans1=ans1+point;
  78.                                 sqrtflag1=0; //清除開(kāi)方標(biāo)志
  79.                                 sqrtflag2=0;//清除開(kāi)方標(biāo)志
  80.                                 if(keysqrt==0)                  //計(jì)算開(kāi)方
  81.                                 {
  82.                                         delayms(5);
  83.                                                 if(keysqrt==0)
  84.                                                 {
  85.                                                         if(beepflag==1) //若開(kāi)聲音則每一次按鍵均鳴叫
  86.                                                         {
  87.                                                                 beep=0;
  88.                                                                 delayms(100);
  89.                                                                 beep=1;
  90.                                                         }
  91.                                                         ans=sqrt(ans1);
  92.                                                         sqrtflag1=1;
  93.                                                         lcdwrite_data(0xe8);
  94.                                                         while(keysqrt==0);
  95.                                                         delayms(10);
  96.                                                         while(keysqrt==0);
  97.                                                         break;
  98.                                                 }
  99.                                 }
  100.                                 sign=num;                 //記住運(yùn)算符號(hào)
  101.                                 lcdwrite_data(num);
  102.                                 break;                   //輸入運(yùn)算符號(hào)則退出第一運(yùn)算數(shù)的輸入
  103.                         }               
  104.                 }
  105.                 while(1)
  106.                 {
  107.                         if(ac==1)
  108.                                 break;          //若清零,則退出輸入
  109.                         if(sqrtflag1==1)  //若第一次按鍵為開(kāi)方,則直接顯示結(jié)果
  110.                         {
  111.                                 break;
  112.                         }
  113.                         if((keyscan()!='N')&&((num>=0&&num<=9)||num=='.'))         //記錄按下的數(shù)字
  114.                         {
  115.                                 if(keynum2<=7)
  116.                                 {
  117.                                         if(num=='.')
  118.                                         {
  119.                                                 lcdwrite_data('.');        //顯示小數(shù)點(diǎn)
  120.                                         }
  121.                                         else
  122.                                                 lcdwrite_num1(num);
  123.                                         num2[keynum2]=num;
  124.                                         keynum2++;
  125.                                 }
  126.                         }
  127.                         else if(num=='='||keysqrt==0)
  128.                         {
  129.                                 sqrtflag2=0;//清除開(kāi)方標(biāo)志
  130.                                 if(keysqrt==0)         //進(jìn)入開(kāi)方
  131.                                 {
  132.                                         delayms(5);
  133.                                         if(keysqrt==0)
  134.                                         {
  135.                                                 sqrtflag2=1;   //開(kāi)方標(biāo)志
  136.                                                 lcdwrite_data(0xe8);  //寫(xiě)開(kāi)方符號(hào)
  137.                                                 if(beepflag==1)        //若開(kāi)聲音則每一次按鍵均鳴叫
  138.                                                 {
  139.                                                         beep=0;
  140.                                                         delayms(100);
  141.                                                         beep=1;
  142.                                                 }
  143.                                                 while(keysqrt==0);
  144.                                                 delayms(10);
  145.                                                 while(keysqrt==0);
  146.                                         }
  147.                                 }
  148.                                 point=0;
  149.                                 for(i=0;keynum2>0;i++)   //計(jì)算按下的數(shù)字的大小
  150.                                 {
  151.                                         if(num2[i]!='.')
  152.                                                 ans2=ans2*10+num2[i];
  153.                                         else if(num2[i]=='.')
  154.                                                 break;
  155.                                         keynum2--;
  156.                                 }
  157.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  158.                                         point=point*10+num2[i];
  159.                                 for(;j>0;j--)
  160.                                         point*=0.1;
  161.                                 if(sqrtflag2!=1)
  162.                                         lcdwrite_data(num);
  163.                                 ans2=ans2+point;
  164.                                 break;                //輸入等于號(hào)則退出第二運(yùn)算數(shù)的輸入
  165.                         }
  166.                         else if(num=='+'||num=='-'||num=='*'||num=='/'||num=='^')
  167.                         {
  168.                                 point=0;
  169.                                 for(i=0;keynum2>0;i++)          //計(jì)算按下的數(shù)字的大小
  170.                                 {
  171.                                         if(num2[i]!='.')
  172.                                                 ans2=ans2*10+num2[i];
  173.                                         else if(num2[i]=='.')
  174.                                                 break;
  175.                                         keynum2--;
  176.                                 }
  177.                                 for(keynum2--,i++,j=0;keynum2>0;j++,i++,keynum2--)
  178.                                         point=point*10+num2[i];
  179.                                 for(;j>0;j--)
  180.                                         point*=0.1;
  181.                                 lcdwrite_data(num);
  182.                                 ans2=ans2+point;
  183.                                 conflag=1;
  184.                                 break;                         //進(jìn)行連續(xù)計(jì)算
  185.                         }
  186.                 }
  187.                 if(ac==1)
  188.                 {        
  189.                         ac=0;
  190.                         continue; //清零后進(jìn)行下一次運(yùn)算
  191.                 }        
  192.                 if(sign=='+')       //計(jì)算結(jié)果
  193.                         ans=ans1+ans2;
  194.                 if(sign=='-')
  195.                         ans=ans1-ans2;
  196.                 if(sign=='*')
  197.                         ans=ans1*ans2;
  198.                 if(sign=='/')
  199.                         ans=ans1/ans2;
  200.                 if(sign=='^')         //計(jì)算多次方
  201.                         ans=pow(ans1,ans2);         
  202.                 if(sqrtflag2==1)        //計(jì)算開(kāi)方
  203.                         ans=sqrt(ans1);
  204.                 lcd_setxy(1,0);
  205.                 if((ans2==0&&sign=='/')||(ans1<0&&sqrtflag2==1))
  206.                         lcdwrite_string("math error");//ans2=0或被開(kāi)方數(shù)小于0時(shí)提示錯(cuò)誤           
  207.                 else lcdwrite_float(ans);                //顯示結(jié)果
  208.                 sqrtflag1=0,newcalc=1;                  //為新的一次運(yùn)算準(zhǔn)備
  209.                 ans1=0;
  210.                 ans2=0;
  211.                 for(i=0;i<8;i++)        //清除按鍵緩存
  212.                         num1[i]=0;
  213.                 for(i=0;i<8;i++)
  214.                         num2[i]=0;
  215.                 if(conflag==1)
  216.                 {
  217.                         conflag=0;
  218.                         goto here;           //跳轉(zhuǎn)到連續(xù)運(yùn)算
  219.                 }
  220.         }
  221. }
  222. /*****初始化程序*****/
  223. void maininit(void)        
  224. {
  225.         delayms(100); //等待液晶初始化
  226.         lcd_init();
  227.         lcd_setxy(0,0);
  228.         lcdwrite_data('0');
  229.         lcd_setxy(0,0);
  230.         IT0=1;//下降沿觸發(fā)
  231.         EX0=1;//開(kāi)外部中斷0
  232.         IT1=1;//下降沿觸發(fā)
  233.         EX1=1;//開(kāi)外部中斷1
  234.         EA=1; //開(kāi)中斷
  235. }
  236. /***清零中斷程序******/
  237. void EX0_int() interrupt 0
  238. {
  239.         if(beepflag==1)        //若開(kāi)聲音則每一次按鍵均鳴叫
  240.         {
  241.                 beep=0;
  242.                 delayms(500);
  243.                 beep=1;
  244.         }
  245.         lcdwrite_com(0x01); //顯示清屏
  246.         lcd_setxy(0,0);
  247.         lcdwrite_data('0');
  248.         lcd_setxy(0,0);
  249.         num='N';                          //數(shù)字初始化
  250.         keynum1=0,keynum2=0,sign=0;
  251.     ans1=0,ans2=0,ans=0,point=0;
  252.         conflag=0,newcalc=0;
  253.         ac=1;
  254. }
  255. /***聲音中斷程序******/
  256. void EX1_int() interrupt 2
  257. {
  258.         beepflag=~beepflag;
  259.         if(beepflag==1)  //若開(kāi)聲音則每一次按鍵均鳴叫
  260.                 {
  261.                 beep=0;
  262.                 delayms(500);
  263.                 beep=1;
  264.         }
  265. }
  266. /*****鍵盤(pán)掃描程序*****/
  267. uchar keyscan()
  268. {        
  269.     num='N';        //若沒(méi)有按下任何按鍵,則返回'N'
  270.     P1=0xfe;        //掃描第一行
  271.     temp=P1;
  272.     temp=temp&0xf0;
  273.     while(temp!=0xf0) //掃描列
  274.     {
  275.         delayms(10);
  276.         temp=P1;
  277.         temp=temp&0xf0;
  278.         while(temp!=0xf0)
  279.         {
  280.             temp=P1;                        
  281.             switch(temp)
  282.             {
  283.                 case 0xee:num=7;
  284.                     break;                                       
  285.                 case 0xde:num=8;
  286.                     break;                                                
  287.                 case 0xbe:num=9;
  288.                     break;
  289.                 case 0x7e:num='/';
  290.                     break;
  291.             }                                                        
  292.             while(temp!=0xf0)         //等待松手
  293.             {
  294.                 temp=P1;
  295.                 temp=temp&0xf0;
  296.             }
  297.         }
  298.     }
  299.     P1=0xfd;                //掃描第二行         
  300.         temp=P1;
  301.         temp=temp&0xf0;
  302.         while(temp!=0xf0) //掃描列
  303.         {
  304.                 delayms(10);
  305.                 temp=P1;
  306.                 temp=temp&0xf0;
  307.                 while(temp!=0xf0)
  308.                 {
  309.                         temp=P1;                        
  310.                         switch(temp)
  311.                         {
  312.                                 case 0xed:num=4;
  313.                                         break;                                       
  314.                                 case 0xdd:num=5;
  315.                                         break;                                                
  316.                                 case 0xbd:num=6;
  317.                                         break;
  318.                                 case 0x7d:num='*';
  319.                                         break;
  320.                         }
  321.                      while(temp!=0xf0)
  322.                         {
  323.                                 temp=P1;
  324.                                 temp=temp&0xf0;                 //等待松手
  325.                         }
  326.                 }
  327.         }
  328.          P1=0xfb;         //掃描第三行
  329.         temp=P1;
  330.         temp=temp&0xf0;
  331.         while(temp!=0xf0) //掃描列
  332.         {
  333.                 delayms(10);
  334.                 temp=P1;
  335.                 temp=temp&0xf0;
  336.                 while(temp!=0xf0)
  337.                 {
  338.                         temp=P1;                        
  339.                         switch(temp)
  340.                         {
  341.                                 case 0xeb:num=1;
  342.                                         break;                                       
  343.                                 case 0xdb:num=2;
  344.                                         break;                                                
  345.                                 case 0xbb:num=3;
  346.                                         break;
  347.                                 case 0x7b:num='-';
  348.                                         break;
  349.                         }
  350.                      while(temp!=0xf0)        //等待松手
  351.                         {
  352.                                 temp=P1;
  353.                                 temp=temp&0xf0;
  354.                         }
  355.                 }
  356.         }
  357.          P1=0xf7;          //掃描第四行
  358.         temp=P1;
  359.         temp=temp&0xf0;
  360.         while(temp!=0xf0) //掃描列
  361.         {
  362.                 delayms(10);
  363.                 temp=P1;
  364.                 temp=temp&0xf0;
  365.                 while(temp!=0xf0)
  366.                 {
  367.                         temp=P1;                        
  368.                         switch(temp)
  369.                         {
  370.                                 case 0xe7:num=0;
  371.                                         break;                                       
  372.                                 case 0xd7:num='.';
  373.                                         break;                                                
  374.                                 case 0xb7:num='=';
  375.                                         break;
  376.                                 case 0x77:num='+';
  377.                                         break;
  378.                         }
  379.                      while(temp!=0xf0)
  380.                         {
  381.                                 temp=P1;
  382.                                 temp=temp&0xf0;                 //等待松手
  383.                         }
  384.                  }
  385.         }
  386.         if(keypow==0)
  387.         {
  388.                 delayms(5);
  389.                 if(keypow==0)
  390.                 {
  391.                         powflag=1;
  392.                         num='^';
  393.                 }
  394.                 while(keypow==0); //掃描多次方按鍵
  395.                 delayms(5);
  396.                 while(keypow==0);
  397.         }
  398.         if(beepflag==1&&num!='N')  //若開(kāi)聲音則每一次按鍵均鳴叫
  399.         {
  400.                 beep=0;
  401.                 delayms(100);
  402.                 beep=1;
  403.         }
  404.     return num;
  405. }
復(fù)制代碼


評(píng)分

參與人數(shù) 4黑幣 +61 收起 理由
安山有狐貍 + 1 贊一個(gè)!
妖行 + 5 很給力!
ZHANGJINGYU + 5 回帖助人的獎(jiǎng)勵(lì)!
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

ID:161497 發(fā)表于 2017-6-2 22:41 | 顯示全部樓層
好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報(bào)

ID:103952 發(fā)表于 2017-6-14 15:03 | 顯示全部樓層

下載地址就在上面哦
回復(fù)

使用道具 舉報(bào)

ID:214665 發(fā)表于 2017-6-26 10:47 | 顯示全部樓層
很厲害啊
回復(fù)

使用道具 舉報(bào)

ID:245246 發(fā)表于 2017-11-2 11:23 | 顯示全部樓層
下載了可以用嗎
回復(fù)

使用道具 舉報(bào)

ID:247636 發(fā)表于 2017-11-10 09:21 來(lái)自觸屏版 | 顯示全部樓層
我想弄這個(gè),試試看
回復(fù)

使用道具 舉報(bào)

ID:294062 發(fā)表于 2018-3-19 15:43 | 顯示全部樓層
看著很不錯(cuò),學(xué)習(xí)一下
回復(fù)

使用道具 舉報(bào)

ID:339591 發(fā)表于 2018-5-28 10:44 | 顯示全部樓層
看起來(lái)很厲害,參考一下
回復(fù)

使用道具 舉報(bào)

ID:341778 發(fā)表于 2018-6-11 15:21 | 顯示全部樓層
很棒很不錯(cuò)
回復(fù)

使用道具 舉報(bào)

ID:350401 發(fā)表于 2018-6-13 10:21 | 顯示全部樓層
nice,最近在做課程設(shè)計(jì),學(xué)到了
回復(fù)

使用道具 舉報(bào)

ID:350967 發(fā)表于 2018-6-13 11:35 | 顯示全部樓層
厲害了
回復(fù)

使用道具 舉報(bào)

ID:354047 發(fā)表于 2018-6-21 18:13 來(lái)自觸屏版 | 顯示全部樓層
里面有沒(méi)有工程
回復(fù)

使用道具 舉報(bào)

ID:162514 發(fā)表于 2018-9-19 08:55 | 顯示全部樓層
下來(lái)玩玩!
回復(fù)

使用道具 舉報(bào)

ID:530642 發(fā)表于 2019-5-9 16:09 | 顯示全部樓層
在哪里下載?
回復(fù)

使用道具 舉報(bào)

ID:258520 發(fā)表于 2019-5-16 17:21 | 顯示全部樓層
能輸入小數(shù)點(diǎn)嗎   
回復(fù)

使用道具 舉報(bào)

ID:553254 發(fā)表于 2019-6-2 21:09 | 顯示全部樓層
感謝分享
回復(fù)

使用道具 舉報(bào)

ID:655531 發(fā)表于 2019-12-3 22:19 | 顯示全部樓層
感謝分享
回復(fù)

使用道具 舉報(bào)

ID:498685 發(fā)表于 2019-12-8 10:35 | 顯示全部樓層
感謝分享,值得學(xué)習(xí),謝謝樓主
回復(fù)

使用道具 舉報(bào)

ID:639069 發(fā)表于 2019-12-19 14:50 來(lái)自觸屏版 | 顯示全部樓層
那個(gè)lc1602_8.h沒(méi)有包含怎么辦
回復(fù)

使用道具 舉報(bào)

ID:669432 發(fā)表于 2019-12-21 18:01 | 顯示全部樓層
已經(jīng)下載了,謝謝大佬
回復(fù)

使用道具 舉報(bào)

ID:681485 發(fā)表于 2020-1-5 19:40 | 顯示全部樓層
這個(gè)的按鍵具體是哪些?要怎么用
回復(fù)

使用道具 舉報(bào)

ID:771836 發(fā)表于 2020-6-7 13:19 | 顯示全部樓層
感謝大佬
回復(fù)

使用道具 舉報(bào)

ID:838120 發(fā)表于 2020-11-8 19:16 | 顯示全部樓層
你這個(gè)能進(jìn)行8*8位的運(yùn)算嗎
回復(fù)

使用道具 舉報(bào)

ID:834848 發(fā)表于 2020-12-27 13:19 來(lái)自觸屏版 | 顯示全部樓層
感謝感謝分享   值得學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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