標(biāo)題: 單片機(jī)計(jì)算器程序(能實(shí)現(xiàn)四位數(shù)與四位數(shù)加減乘除)基于C語言 現(xiàn)無任何漏洞 [打印本頁]

作者: 1428327352    時(shí)間: 2019-4-12 19:23
標(biāo)題: 單片機(jī)計(jì)算器程序(能實(shí)現(xiàn)四位數(shù)與四位數(shù)加減乘除)基于C語言 現(xiàn)無任何漏洞
本帖最后由 1428327352 于 2019-4-19 19:29 編輯

由于新學(xué)習(xí)的單片機(jī)C語言,寫程序手法稚嫩,但適合新手做參考。算法比較繁瑣,但是經(jīng)過我一上午的修復(fù),現(xiàn)在已經(jīng)沒有任何漏洞了。。
四位數(shù)于四位數(shù)之間的加減乘除計(jì)算
已經(jīng)能夠顯示小數(shù)點(diǎn)后兩位,例:10/3=3.33;1/2=0.5;1/20=0.05
能夠計(jì)算負(fù)數(shù),例:1-20=-19;
基于1602液晶顯示屏
由于按鍵個(gè)數(shù)原因,目前只打了以下16個(gè)鍵
以后在擴(kuò)展的話會(huì)更新
1 2 3 +
4 5 6 -
7 8 9 *
ce 0 = /


1602我的想法是送一行地址,再送一行數(shù)據(jù)
計(jì)算器主要分為顯示程序,計(jì)算程序,和按鍵掃描程序
將其結(jié)合
電路圖;





元器件:



源代碼:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar z,x,num,key,m,n;
uint a;                                                       //a,b代表算子
ulong b, c;                                                         //這個(gè)c代表結(jié)果,原只想將c用ulong的,因?yàn)閏是結(jié)果需要的數(shù)據(jù)范圍大,但是試了不行,只有將
ac或bc或abc設(shè)成大范圍才可以。在這里為節(jié)省存儲(chǔ),設(shè)了bc?梢哉_\(yùn)行到一個(gè)很大的數(shù)了。
                                                                     
uchar c1,c2,c3,c4,c5,c6,c7,c8;
            
void delay(uint xms)                           
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
sbit rs=P2^6;
sbit rw=P2^5;
sbit en=P2^7;
uchar code table[]="ERROR!";                                                  // 在除數(shù)為0時(shí)直接報(bào)錯(cuò)

void write_com(uchar com)      //д????                                   //讀命令
{
rs=0;
rw=0;
delay(5);
P0=com;
delay(5);
en=1;
delay(5);
en=0;
delay(5);
}

void write_date(uchar date)       //д????                                  //讀數(shù)據(jù)
{
rs=1;
rw=0;
delay(5);
P0=date;
delay(5);
en=1;
delay(5);
en=0;
    delay(5);
}
void init()           //?????                                               初始化函數(shù)
{
n=0;
m=5;
    write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
write_date('0');
}
short keycheckdown()                                                        /* ???????????? */鍵盤掃描函數(shù),帶回一個(gè)返回值,所以這里不用void
{

              short temp1,temp2,temp,x=0xff;
              P1=0xf0;                                                                                    /* ???????????????? */
              delay(20);                                                        /* ??? */
              temp1=P1;                                                                                    /* ?????????????? */
             P1=0xff;
              delay(20);                                                        /* ??? */
              P1=0x0f;                                                                                    /* ???????????????? */
           delay(20);                                                        /* ??? */            
              temp2=P1;                                                                                    /* ?????????????? */
              P1=0xff;
              temp=(temp1&0xf0)|(temp2&0xf);              /* ?????ζ?????????? */
              switch(temp)                                                                      /* ???????????????ж????λ?? */
              {


                            case 0x7e :x=0x0d;break;//  ????/  
                            case 0x7d :x=0x0e; break;// ????=            
                            case 0x7b: x=0;    break;// ????0
                            case 0x77 :x=0x0f; break;// ????CE

                            case 0xbe :x=0x0c;break;//               ????*
                            case 0xbd :x=0x09;break; //  ????9
                            case 0xbb :x=0x08;break; //  ????8
                            case 0xb7 :x=0x07;break; //               ????7

                           case 0xde :x=0x0b;break;//  ????-
                           case 0xdd:x=0x06;break; //               ????6
                           case 0xdb :x=0x05;break; //               ????5
                           case 0xd7 :x=0x04;break; //               ????4

                            case 0xee :x=0x0a; break;// ????+
                            case 0xed :x=0x03;break;              //  ????3
                            case 0xeb :x=0x02;break;              //  ????2
                            case 0xe7 :x=0x01;break;              //  ????1

                            default :x=0xff;
              }
              return x;                                                                                    /* ???????? */     返回x
}

      void axian()                                                     //算子a的顯示程序
        {
         
     uchar a1,a2,a3,a4;
        write_com(0x01);
      a1=a%10000/1000;    //?    0
              a2=a%1000/100;      //??    0
              a3=a%100/10;        //?   1
              a4=a%10;            //??    2
if(999<a)  {
     write_com(0x80);   
     write_date('0'+a1);
     delay(5);
   
     }  
if(99<a)   {
   
     write_com(0x81);
     write_date('0'+a2);
     delay(5);
   
     }
if(9<a)   {
   
     write_com(0x82);
     write_date('0'+a3);
     delay(5);
        
     }   
if(0<a)  {
   
     write_com(0x83);
     write_date('0'+a4);
     delay(5);

     }
      }
  void bxian()                                                 //算子b的4位,即上限為9999,a上限也是9999;
   {  
     uchar b1,b2,b3,b4;                          // 1*10+2=12
    b1=b%10000/1000;    //?    0
             b2=b%1000/100;      //??    0
             b3=b%100/10;        //?   1
             b4=b%10;            //??    2
    if(999<b)
    {
     write_com(0x88);   
     write_date('0'+b1);
     delay(5);
   
     }  
if(99<b)   {
   
     write_com(0x89);
     write_date('0'+b2);
     delay(5);
   
     }
if(9<b)   {
   
     write_com(0x8a);
     write_date('0'+b3);
     delay(5);
      
     }   
if(0<b)  {
   
     write_com(0x8b);
     write_date('0'+b4);
     delay(5);
     }
if(b==0)   {  init();                                                               //若除數(shù)為0,初始化并且報(bào)錯(cuò)
      write_com(0x80);
      for(num=0;num<6;num++)
      {
       write_date(table[num]);
       delay(5);
      }
     }
     }

  void gong()                                                            這個(gè)是一些程序中重復(fù)使用的部分,將其提取成一個(gè)子函數(shù),會(huì)更簡(jiǎn)潔
  {
    if(c>999)
{
  write_com(0xc5);
  write_date('0'+c5);
  delay(5);

     }  
if(c>99)  
{  

  write_com(0xc6);   
  write_date('0'+c6);
  delay(5);
  
  }
if(c>9)  
{  

  write_com(0xc7);
  write_date('0'+c7);
  delay(5);
   }   
if(c>0)
{

  
  write_com(0xc8);
  write_date('0'+c8);
  delay(5);
  }
  }   
   
  void jian()                                                                   減法會(huì)出現(xiàn)負(fù)號(hào),需要特殊處理,顯示程序就和其他三個(gè)不一樣了
  {
    c5=c%10000/1000;    //?    0
             c6=c%1000/100;      //??    0
             c7=c%100/10;        //?   1
             c8=c%10;  
    if(z==2)                                                                 當(dāng)減號(hào)鍵被按下時(shí)
  {
   if(b>a)                                                                      當(dāng)后一個(gè)數(shù)大于前一個(gè)數(shù)時(shí)
   {
    write_com(0xc4);                                                      顯示負(fù)號(hào)
    write_date('-');
    delay(5);
   if(b-a>999)                                                             顯示負(fù)號(hào)后面的結(jié)果
   {
    write_com(0xc5);
    write_date('0'+c5);
    delay(5);
    }
   if(b-a>99)
   {
    write_com(0xc6);
    write_date('0'+c6);
    delay(5);
    }
   if(b-a>9)
   {
    write_com(0xc7);
    write_date('0'+c7);
    delay(5);
    }
   if(b-a>0)
   {
    write_com(0xc8);
    write_date('0'+c8);
    delay(5);
    }
    }
    if(a>b)                                                                 如果前數(shù)大于后數(shù)的話
    {
    gong();
    }
   }   
  }


void chu()                                                                除號(hào)會(huì)出現(xiàn)小數(shù)點(diǎn),所以將其特殊處理,自成函數(shù)
  {
   if(z==4)
   {
     c=a*100/b;
     c1=c/100000;
     c2=c%100000/10000;
     c3=c%10000/1000;
     c4=c%1000/100;
     c6=c%100/10;
     c7=c%10;
if(a%b!=0)                                                           如果不能整除
{
if(c>100)
{  
if(c>99999)
{

  write_com(0xc1);
  write_date('0'+c1);
  delay(5);

  }
if(c>9999)
{

  write_com(0xc2);
  write_date('0'+c2);
  delay(5);

  
  }
if(c>999)
{

  write_com(0xc3);
  write_date('0'+c3);
  delay(5);

  
  }
if(c>99)
{

  write_com(0xc4);
  write_date('0'+c4);
  delay(5);

  
  }
  write_com(0xc5);
  write_date('.');
  delay(5);
if(c>9)
{

  write_com(0xc6);
  write_date('0'+c6);
  delay(5);

  
  }
  write_com(0xc7);
  write_date('0'+c7);
  delay(5);
  }
}

if(9<c&&c<99)                                                    在這里需注意不能寫成9<c<99!!
{
  write_com(0xc4);
  write_date('0');
  delay(5);
     write_com(0xc5);
  write_date('.');
  delay(5);
  if(c>9)
  {
   write_com(0xc6);
   write_date('0'+c6);
   delay(5);
  }
    write_com(0xc7);
   write_date('0'+c7);
   delay(5);
  }
  if(c<9)
  {
   write_com(0xc4);
   write_date('0');
   delay(5);
      write_com(0xc5);
   write_date('.');
   delay(5);
   write_com(0xc6);
   write_date('0');
   write_com(0xc7);
   write_date('0'+c7);
   delay(5);
  }   
}

  
if(a%b==0)                          如果能夠整除
{
  c=a/b;
  c1=c/1000;
  c2=c%1000/100;
  c3=c%100/10;
  c4=c%10;
  if(c>999)
  {
   write_com(0xc1);
   write_date('0'+c1);
   delay(5);
   }
  if(c>99)
  {
   write_com(0xc2);
   write_date('0'+c2);
   delay(5);
   }
  if(c>9)
  {
   write_com(0xc3);
   write_date('0'+c3);
   delay(5);
   }
   if(c>0)
  {
   write_com(0xc4);
   write_date('0'+c4);
   delay(5);
   }
   }   
   }  
   }

      void cxian()                                                                     c的顯示程序
   {  
    if(z==1||z==3)                                                                         若按下的是加號(hào)或乘號(hào),因?yàn)闇p法可能出現(xiàn)-,除法可能出現(xiàn)".",所以顯示要分開
  {  
   
    c1=c%100000000/10000000;
    c2=c%10000000/1000000;
    c3=c%1000000/100000;
    c4=c%100000/10000;            // 1*10+2=12
    c5=c%10000/1000;    //?    0
             c6=c%1000/100;      //??    0
             c7=c%100/10;        //?   1
             c8=c%10;            //??    2
  
    if(9999999<c)
{
  write_com(0xc1);
  write_date('0'+c1);
  delay(5);

  }   
   if(c>999999)
{
  write_com(0xc2);
  write_date('0'+c2);
  delay(5);
  }
   if(c>99999)
{

  write_com(0xc3);
  write_date('0'+c3);
  delay(5);

  }
   if(c>9999)
{

  write_com(0xc4);
  write_date('0'+c4);
  delay(5);

  
  }
  gong();
}
}
     
  
  
  


void eql()                                                                          計(jì)算程序
{   
  
     switch(z)
     {
   case 0: break;
  case 1: c=a+b;  break;
  case 2: c=a-b;
    if(b>a)
    {
     c=b-a;
     }
    break;
  case 3: c=a*b;  break;
  case 4: c=a/b;  break;
  }
}   

  
   void main()                                                          主函數(shù)
   {
   uint key;                                                              
    init();
     while(1)
   {
    key=keycheckdown();                             將返回的值x賦給key
  if(0xff!=key)
  {
   if(key<10)                        
   {
    if(n<4)                                              n初始值為0, 每按下一次,n加一,當(dāng)按下第五次時(shí)就不執(zhí)行此if語句。用此方法將a的值固定
    {
     a=a*10+key;
     m=5;
     axian();
     n++;
    }
    if(m<4)                                            m的初始值為5,此時(shí)不會(huì)進(jìn)入這個(gè)程序,只有在運(yùn)算符打出后,才將m的值命令得符合這個(gè)if語句
    {
     b=b*10+key;
     n=5;
     bxian();
     m++;
    }
    }
    else
    {
     switch(key)                                                            判斷是那個(gè)運(yùn)算符,并且將其顯示出來。
     {
      case 0x0a:
      n=5;
      m=0;                                                                   在運(yùn)算符給出后,放開后一個(gè)數(shù),可以打后一個(gè)數(shù)了
      z=1;
      write_com(0x85);
      write_date('+');
      break;

      case 0x0b:
      n=5;
      m=0;
      z=2;
      write_com(0x85);
      write_date('-');
      break;

      case 0x0c:
      n=5;
      m=0;
      z=3;
      write_com(0x85);
      write_date('*');
      break;

      case 0x0d:
      n=5;
      m=0;
      z=4;
      write_com(0x85);
      write_date('/');
      break;

      case 0x0e:                                          當(dāng)是等號(hào)時(shí),鎖定兩個(gè)算子a,b,此時(shí)已經(jīng)固定
      m=5;
      n=5;
      eql();                                                  
  對(duì)a,b進(jìn)行計(jì)算

      jian();  
      chu();                                          

      write_com(0xc0);
      write_date('=');
      cxian();
      break;

      case 0x0f:                                           ce鍵,清零
      n=0;
      z=0;
      m=5;
      a=0;
      b=0;
      c=0;
      init();
      break;
     }
     do{P1=0xf0;}
     while(P1!=0xf0);
    }
   }   
   }
  }





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