找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机设计简易计算器(Word格式文档+代码下载)

[复制链接]
跳转到指定楼层
楼主
ID:466603 发表于 2019-1-11 17:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
根据所学单片机知识,设计一简易计算器,要求至少用到 键盘,LED数码管,LCD1602液晶,ADC0809,DA0832,串口,等中的两种,每个项目中至少包含 定时器,总线,中断中的两种。
设计方案:应用矩阵键盘,LCD1602,单片机,74HC21与门,总线,中断设计简易计算器。
实验内容:
              1、P0口接上拉电阻做液晶输出端口,连接图如实验原理图所示。
              2、键盘接在P1口上,如实验原理图所示,并用74HC21与门实现中断请求。
              3、程序设计,见文后。
实验原理图(如下):
键盘接口图:
74HC21与门接线图:
上拉电阻:
LCD1602液晶:
实验效果:
程序设计:
#include<reg51.h>
#include<absacc.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcden=P2^3; //定义引脚 E 使能
sbit rs=P2^4;
sbit rw=P2^0;
sbit busy=P0^7;
sbit p33=P3^3;
char i,j,temp,num,num_1;
long a,b,c;     //a,第一个数 b,第二个数 c,得数

uchar flag,fuhao;//flag表示是否有符号键按下,fuhao表征按下的是哪个符号
uchar code table[]={
                    7,8,9,0,
                    4,5,6,0,
                    1,2,3,0,
                    0,0,0,0};

uchar code table1[]={
                    7,8,9,0x2f-0x30,   //按键标值 0x2f-0x30是将字符转化为数字,与后面的0x30+i抵消,得i值
                    4,5,6,0x2a-0x30,
                    1,2,3,0x2d-0x30,
                    0x01-0x30,0,0x3d-0x30,0x2b-0x30 //0x01是清屏命令
                    };

void delay(uchar z)   // 延迟函数
{
     uchar y;
     for(z;z>0;z--)
     for(y=0;y<110;y++);
}

void check() // 判断忙或空闲
{
    do{
        P0=0xFF;
        rs=0;         
        rw=1;          //读 rs rw 值为01时,忙标志和地址计数器读出
        lcden=0;       //E=0,禁止读写
        delay(1);      //等待,液晶显示器处理数据
        lcden=1;       //E=1,允许读写
      }while(busy==1); //判断是否为空闲,1为忙,0为空闲
}

void write_com(uchar com) // 写指令函数
{
      P0=com;             //com指令付给P0口
      rs=0;
      rw=0;
      lcden=0;
      check();
      lcden=1;
}

void write_date(uchar date) // 写数据函数
{
    P0=date;
    rs=1;
    rw=0;
    lcden=0;
    check();
    lcden=1;

}
void init() //初始化
{
    lcden=1;         //使能信号为高电平
    write_com(0x38); //功能设置命令:8位,2行 DDRAM的地址
write_com(0x0e); //显示开,光标开,不闪烁
write_com(0x06); //增量方式不移位
write_com(0x80); //设置访问地址
  num_1=0;
    i=0;
    j=0;
    a=0;     //第一个参与运算的数
    b=0;     //第二个参与运算的数
    c=0;   //结果值
    flag=0; //flag表示是否有符号键按下,
    fuhao=0; // fuhao表征按下的是哪个符号
}

void keyscan(void)// 键盘扫描程序
{
    void int0();

   P1=0xfe;
   if(P1!=0xfe)
   {
       delay(20);//20ms
       if(P1!=0xfe)
       {
            temp=P1&0xf0;
            switch(temp)
               {
                 case 0xe0:num=0;
                 break;
                 case 0xd0:num=1;
                 break;
                 case 0xb0:num=2;
                 break;
                 case 0x70:num=3;
                 break;
               }
         }
         while(P1!=0xfe);
         if(num==0||num==1||num==2)//如果按下的是'7','8'或'9'
         {
             if(j!=0)
             {
                 write_com(0x01); //清屏命令
                 j=0;
             }

             if(flag==0)//没有按过符号键
             {
                 a=a*10+table[num]; //a的初值为'0',结果为输入a值
             }
              else      //如果按过符号键
              {
                b=b*10+table[num]; //b的初值为'0' ,结果为输入b值
              }
           }
          else         //如果按下的是'/'
          {
             flag=1;
             fuhao=4; //4表示除号已按
           }
          i=table1[num];
          write_date(0x30+i);//将数字转化为字符,对应前面的table1中的i-0x30
        }   
        P1=0xfd;
       if(P1!=0xfd)
       {
           delay(5);
           if(P1!=0xfd)
           {
               temp=P1&0xf0;
               switch(temp)
               {
                 case 0xe0:num=4;
                 break;
      case 0xd0:num=5;
                 break;
                 case 0xb0:num=6;
                 break;
                 case 0x70:num=7;
                 break;
                }
             }
             while(P1!=0xfd);
             if(num==4||num==5||num==6)//如果按下的是'4','5'或'6'
             {
                 if(j!=0)
                {
                     write_com(0x01); //清屏命令
                     j=0;
                  }
                  if(flag==0)//没有按过符号键
                  {
                     a=a*10+table[num];    //输入a值
                  }
                   else//如果按过符号键
                  {
                       b=b*10+table[num]; //输入b值
                   }
               }
              else//如果按下的是'*'
              {
                  flag=1;
                  fuhao=3;//3表示乘号已按
               }
               i=table1[num];
               write_date(0x30+i);
      
          }
          P1=0xfb;
          if(P1!=0xfb)
          {
              delay(5);
              if(P1!=0xfb)
              {
                 temp=P1&0xf0;
                  switch(temp)
                 {
                    case 0xe0:num=8;
                     break;
                    case 0xd0:num=9;
                    break;
                    case 0xb0:num=10;
                    break;
                    case 0x70:num=11;
                    break;
                   }
                }
                while(P1!=0xfb);
                if(num==8||num==9||num==10)//如果按下的是'1','2'或'3'
                {
                     if(j!=0)
                     {
                       write_com(0x01); //清屏
                        j=0;
                      }
                      if(flag==0)//没有按过符号键
                      {
                         a=a*10+table[num];
                       }
                      else//如果按过符号键
                      {
                         b=b*10+table[num];
                        }
                   }
                else if(num==11)//如果按下的是'-'

                {
                   flag=1;
                   fuhao=2;//2表示减号已按
      }
               i=table1[num];
               write_date(0x30+i);
      
            }
   
           P1=0xf7;
           if(P1!=0xf7)
           {
              delay(5);
              if(P1!=0xf7)
              {
                  temp=P1&0xf0;
                  switch(temp)
                  {
                     case 0xe0:num=12;
                     break;
                     case 0xd0:num=13;
                     break;
                     case 0xb0:num=14;
                     break;
                     case 0x70:num=15;
                     break;
                    }
                 }
                while(P1!=0xf7);
               switch(num)
               {
                 case 12:
     {
         write_com(0x01);
         a=0;
         b=0;
         flag=0;
         fuhao=0;
     }              //按下的是"清零"
                 break;
                 case 13:   //按下的是"0"
     {               
                     if(flag==0)//没有按过符号键
                     {
                         a=a*10;
                         write_date(0x30);
                     }
                    else if(flag==1)//如果按过符号键
                    {
                         b=b*10;
                         write_date(0x30);
                     }
                  }
              break;
              case 14:
     {
         j=1;
                  if(fuhao==1)
      {
          write_com(0x80+0x4f);//按下等于键,光标前进至第二行最后一个显示处
write_com(0x04); //设置从后住前写数据,每写完一个数据,光标后退一格
                      c=a+b;
                      while(c!=0)
                      {
                          write_date(0x30+c%10);
                          c=c/10;
                       }
                      write_date(0x3d);     //再写"="
                      a=0;b=0;flag=0;fuhao=0;
                   }

                   else if(fuhao==2)
       {
           write_com(0x80+0x4f);//光标前进至第二行最后一个显示处
                       write_com(0x04);     //设置从后住前写数据,每写完一个数据,光标后退一格(这个照理说顺序不对,可显示和上段一样)
                       if(a-b>0)
                       {c=a-b;}
                       else
                       {c=b-a;}
                       while(c!=0)
                       {
                           write_date(0x30+c%10);
c=c/10;
                        }
                       if(a-b<0)
                       write_date(0x2d);
                       write_date(0x3d);     //再写"="           
                       a=0;b=0;flag=0;fuhao=0;
                     }
                   else if(fuhao==3)
       {
          write_com(0x80+0x4f);
write_com(0x04);
                       c=a*b;
                       while(c!=0)
                        {
                           write_date(0x30+c%10);
                           c=c/10;
                         }
                      write_date(0x3d);     
                      a=0;b=0;flag=0;fuhao=0;
                    }
                   else if(fuhao==4)
       {
          write_com(0x80+0x4f);
                      write_com(0x04);
                i=0;
                      c=(long)(((float)a/b)*1000);
                      while(c!=0)
                       {
                           write_date(0x30+c%10);
                           c=c/10;
                           i++;
                           if(i==3)    //设置小数点位数
                           write_date(0x2e);
                        }
                      if(a/b<=0)
                      write_date(0x30);
                      write_date(0x3d);                              
                      a=0;b=0;flag=0;fuhao=0;
                    }

                  }
                 break;
               case 15:
      {
           write_date(0x30+table1[num]);
      flag=1;
      fuhao=1;
       }
                    break;
               }
           }
     
        P1=0xf0;
}

void main()         //主函数
{
   init();

   EX1=1;
   EA=1;
   IT1=1;
   p33=1;
P1=0xf0;
   while(1)
   {
   
   if(p33==0){
      keyscan();}
   }
}

void int0() interrupt 2 using 1    //中断
{
   
if(p33==1)
{
   p33=0;}
}


完整的Word格式文档51黑下载地址:
单片机设计简易计算器.doc (258 KB, 下载次数: 20)


评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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