找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4963|回复: 0
打印 上一主题 下一主题
收起左侧

单片机计算器程序(能实现四位数与四位数加减乘除)基于C语言 现无任何漏洞

[复制链接]
跳转到指定楼层
楼主
本帖最后由 1428327352 于 2019-4-19 19:29 编辑

由于新学习的单片机C语言,写程序手法稚嫩,但适合新手做参考。算法比较繁琐,但是经过我一上午的修复,现在已经没有任何漏洞了!!!
四位数于四位数之间的加减乘除计算
已经能够显示小数点后两位,例:10/3=3.33;1/2=0.5;1/20=0.05
能够计算负数,例:1-20=-19;
基于1602液晶显示屏
由于按键个数原因,目前只打了以下16个键
以后在扩展的话会更新
1 2 3 +
4 5 6 -
7 8 9 *
ce 0 = /


1602我的想法是送一行地址,再送一行数据
计算器主要分为显示程序,计算程序,和按键扫描程序
将其结合
电路图;





元器件:



源代码:
#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;                                                         //这个c代表结果,原只想将c用ulong的,因为c是结果需要的数据范围大,但是试了不行,只有将
ac或bc或abc设成大范围才可以。在这里为节省存储,设了bc。可以正常运行到一个很大的数了。
                                                                     
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!";                                                  // 在除数为0时直接报错

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)       //д????                                  //读数据
{
rs=1;
rw=0;
delay(5);
P0=date;
delay(5);
en=1;
delay(5);
en=0;
    delay(5);
}
void init()           //?????                                               初始化函数
{
n=0;
m=5;
    write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
write_date('0');
}
short keycheckdown()                                                        /* ???????????? */键盘扫描函数,带回一个返回值,所以这里不用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();                                                               //若除数为0,初始化并且报错
      write_com(0x80);
      for(num=0;num<6;num++)
      {
       write_date(table[num]);
       delay(5);
      }
     }
     }

  void gong()                                                            这个是一些程序中重复使用的部分,将其提取成一个子函数,会更简洁
  {
    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()                                                                   减法会出现负号,需要特殊处理,显示程序就和其他三个不一样了
  {
    c5=c%10000/1000;    //?    0
             c6=c%1000/100;      //??    0
             c7=c%100/10;        //?   1
             c8=c%10;  
    if(z==2)                                                                 当减号键被按下时
  {
   if(b>a)                                                                      当后一个数大于前一个数时
   {
    write_com(0xc4);                                                      显示负号
    write_date('-');
    delay(5);
   if(b-a>999)                                                             显示负号后面的结果
   {
    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)                                                                 如果前数大于后数的话
    {
    gong();
    }
   }   
  }


void chu()                                                                除号会出现小数点,所以将其特殊处理,自成函数
  {
   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)                                                                         若按下的是加号或乘号,因为减法可能出现-,除法可能出现".",所以显示要分开
  {  
   
    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()                                                                          计算程序
{   
  
     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()                                                          主函数
   {
   uint key;                                                              
    init();
     while(1)
   {
    key=keycheckdown();                             将返回的值x赋给key
  if(0xff!=key)
  {
   if(key<10)                        
   {
    if(n<4)                                              n初始值为0, 每按下一次,n加一,当按下第五次时就不执行此if语句。用此方法将a的值固定
    {
     a=a*10+key;
     m=5;
     axian();
     n++;
    }
    if(m<4)                                            m的初始值为5,此时不会进入这个程序,只有在运算符打出后,才将m的值命令得符合这个if语句
    {
     b=b*10+key;
     n=5;
     bxian();
     m++;
    }
    }
    else
    {
     switch(key)                                                            判断是那个运算符,并且将其显示出来。
     {
      case 0x0a:
      n=5;
      m=0;                                                                   在运算符给出后,放开后一个数,可以打后一个数了
      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:                                          当是等号时,锁定两个算子a,b,此时已经固定
      m=5;
      n=5;
      eql();                                                  
  对a,b进行计算

      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);
    }
   }   
   }
  }

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表