找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机实现4*4矩阵式键盘计算器源程序+Proteus仿真

[复制链接]
跳转到指定楼层
楼主
以AT89C51单片机为核心实现一个4*4矩阵式键盘计算器,该计算器可以实现基本加减乘除功能,并且用LCD显示键盘输入数和运算符号。


单片机源程序如下:
  1. #include<reg51.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. unsigned char n;
  5. float idata a,b;                                                                //两个操作数       
  6. void key_scan(void);                                        //键盘扫描
  7. void init();                                                        //LCD初始化
  8. void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//字符串显示
  9. void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat);     //字符显示
  10. void write_com(unsigned char com);

  11. sbit lcden=P2^7;                                                        //读写控制输入端
  12. sbit rw=P2^6;                                                                //读写控制端
  13. sbit rs=P2^5;                                                                //指令与数据选择
  14. sbit busy=P0^7;                                                        //LCD忙碌标识

  15. void delay(unsigned int i)                                        //延时程序
  16. {       
  17.         unsigned int n;
  18.         for(n=0;n<=i;n++);
  19. }

  20. void main()
  21. {
  22.         char idata temp[16];                                                //临时存储区
  23.         char i=0,j=0,fuhao;                                                //i,j分别为temp与LCD的数据指针
  24.         bit flag=0,dh=0,fh=0,xsd=0;
  25. //flag=0:操作数1,flag=1:操作数2;dh=1时表示已输入等号;fh负号;xsd小数点
  26.         init();                                                                        //小数点
  27.         LCD_dsp_string(4,0,"Welcome!");                               
  28.         do
  29.         {
  30.                  key_scan();                                                                       
  31.         } while(n==17);                                                        //等待按键
  32.         write_com(0x01);                                                        //清屏
  33.         while(1)
  34.         {
  35.                 key_scan();                                                        //等待按键
  36.                 if((dh==1)&(flag==1)&(n!=17))                //一次计算完毕后执行
  37.                 {
  38.                         write_com(0x01);                                        //清屏
  39.                         LCD_dsp_string(0,0,temp);                //输出上次计算的结果
  40.                         j=0;                                                                                       
  41.                         i=0;
  42.                         flag=0;
  43.                         fh=0;                                                                                                                       
  44.                         while(temp[i++]!='\0') j++;                                    
  45. //将temp数据指针移向后一个空位,将LCD显示指针移向下一个空位
  46.                 }
  47.                 if((i==0)&(n=='-')&(fh==0))                        //如果输入的第一个数是负数则执行
  48.                 {
  49.                         fh=1;                                                                //表示有负号
  50.                          temp[0]='-';                                                //保存负号
  51.                         i++;
  52.                         LCD_dsp_char(j++,0,n);                        //输出减号
  53.                         if(flag==0) continue;                                                       
  54.                 }
  55.                 if(((n>='0')&(n<='9')|((n=='c')&(xsd==0)))&(dh==0))
  56.                 {
  57.                         if(n=='c')
  58.                         {       
  59.                                 n='.';
  60.                                 xsd=1;                                                        //防止再次按下c后继续出现小数点
  61.                         }
  62.                         temp[i++]=n;                                        //保存输入的数字
  63.                         LCD_dsp_char(j++,0,n);                //显示并将光标移至下一位(光标未显示)
  64.                
  65. }
  66.                 if(((n=='+')|(n=='-')|(n=='*')|(n=='/'))&((flag==0)|(dh==1)))
  67. //输入完第一个操作数之后或者完成一次计算之后按下运算符按键时执行
  68.                 {
  69.                          flag=1;                                                //之后输入的操作数是第二个操作数
  70.                         fuhao=n;
  71.                         temp[i]='\0';                                        //表示为字符串
  72.                         a=atof(temp);                                        //转换为数据
  73.                         i=0;
  74.                         dh=0;
  75.                         xsd=0;                                                //之后第二个操作数中可以添加一个小数点
  76.                         switch(n)
  77.                         {
  78.                                  case '+': LCD_dsp_char(j++,0,n); break;
  79.                                 case '-': LCD_dsp_char(j++,0,n);
  80.                                                   fh=0;        break;
  81.                                 case '*': LCD_dsp_char(j++,0,n); break;
  82.                                 case '/': LCD_dsp_char(j++,0,n); break;
  83.                         }                                                                //显示运算符
  84.                 }
  85.                 if((n=='=')&(flag==1))                        //已输入完第二个操作数并按下等号
  86.                 {
  87.                         dh=1;
  88.                         temp[i]='\0';
  89.                         b=atof(temp);
  90.                         i=0;
  91.                         xsd=0;
  92.                         LCD_dsp_char(j,0,'=');                //显示等号
  93.                         switch(fuhao)
  94.                         {
  95.                                  case '+': a=a+b; break;
  96.                                 case '-': a=a-b; break;
  97.                                 case '*': a=a*b; break;
  98.                                 case '/': a=a/b; break;
  99.                         }                                                                //计算
  100.                         if(a>9999)
  101.                         {
  102.                                 sprintf(temp,"%s","Error");       
  103. //若计算结果超过四位数则输出错误信息
  104.                                 LCD_dsp_string(0,1,temp);
  105.                                 n=17;
  106.                                 do
  107.                                 {
  108.                                         key_scan();                                                                       
  109.                                 }while(n==17);                        //等待按键
  110.                                 write_com(0x01);                        //清屏
  111.                                 a=b=0;
  112.                                 fuhao=0;
  113.                                 flag=0;
  114.                                 i=0;
  115.                                 j=0;
  116.                                 dh=0;
  117.                                 xsd=0;
  118.                                 fh=0;                                                //恢复初始化
  119.                         }
  120.                         else
  121.                         {
  122.                                 sprintf(temp,"%g",a);        //输出计算结果
  123.                                 LCD_dsp_string(0,1,temp);
  124.                         }
  125.                 }
  126.                 if(n=='c')                                                                        //按下清除键
  127.                 {
  128.                         write_com(0x01);                                                //清屏
  129.                         a=b=0;
  130.                         fuhao=0;
  131.                         flag=0;
  132.                         i=0;
  133.                         j=0;
  134.                         dh=0;
  135.                         xsd=0;
  136.                         fh=0;                                                                //恢复初始化
  137.                 }
  138.         }
  139. }


  140. void key_scan(void)
  141. {         
  142.         unsigned char temp;
  143.         P1=0xfe;
  144.         if(P1!=0xfe)
  145.         {
  146.                    delay(200);
  147.                    if(P1!=0xfe)
  148.                    {
  149.                     temp=P1&0xf0;
  150.                             switch(temp)
  151.                     {
  152.                              case 0xe0:n='c';break;
  153.                              case 0xd0:n='0';break;
  154.                              case 0xb0:n='=';break;
  155.                              case 0x70:n='+';break;
  156.                     }
  157.                    }
  158.                    while(P1!=0xfe);
  159.         }
  160.         else
  161.         {
  162.         P1=0xfd;
  163.         if(P1!=0xfd)
  164.         {
  165.                    delay(200);
  166.                    if(P1!=0xfd)
  167.                    {
  168.                     temp=P1&0xf0;
  169.                             switch(temp)
  170.                     {
  171.                              case 0xe0:n='1';break;
  172.                              case 0xd0:n='2';break;
  173.                              case 0xb0:n='3';break;
  174.                              case 0x70:n='-';break;
  175.                     }
  176.                    }
  177.                    while(P1!=0xfd);
  178.         }
  179.         else{
  180.         P1=0xfb;
  181.         if(P1!=0xfb)
  182.         {
  183.                    delay(200);
  184.                    if(P1!=0xfb)
  185.                    {
  186.                     temp=P1&0xf0;
  187.                             switch(temp)
  188.                     {
  189.                              case 0xe0:n='4';break;
  190.                              case 0xd0:n='5';break;
  191.                              case 0xb0:n='6';break;
  192.                              case 0x70:n='*';break;
  193.                     }
  194.                    }
  195.                    while(P1!=0xfb);
  196.         }
  197.         else{
  198.         P1=0xf7;
  199.         if(P1!=0xf7)
  200.         {
  201.                    delay(200);
  202.                    if(P1!=0xf7)
  203.                    {
  204.                     temp=P1&0xf0;
  205.                             switch(temp)
  206.                     {
  207.                              case 0xe0:n='7';break;
  208.                              case 0xd0:n='8';break;
  209.                              case 0xb0:n='9';break;
  210.                              case 0x70:n='/';break;
  211.                     }
  212.                    }
  213.                    while(P1!=0xf7);
  214.         }
  215.         else n=17;
  216.         }}}       
  217. }

  218. void check()                                                                 //判断LCD是否忙碌
  219. {
  220.         do
  221.         {
  222.                 P0=0xff;
  223.                 rs=0;
  224.                 rw=1;
  225.                 lcden=0;
  226.                 delay(100);
  227.                 lcden=1;
  228.          }while(busy==1);                                                //当busy=1,即LCD忙时,等待
  229. }
  230. void write_com(unsigned char com)     //写显示命令
  231. {
  232.         P0=com;
  233.         rs=0;
  234.         rw=0;
  235.         lcden=0;
  236.         check();
  237.         lcden=1;
  238. }
  239. void write_data(unsigned char date) //写显示数据
  240. {
  241.         P0=date;
  242.         rs=1;
  243.         rw=0;
  244.         lcden=0;
  245.         check();
  246.         lcden=1;
  247. }
  248. void init()                                                                 //初始化LCD
  249. {
  250.         write_com(0x38);                                                //16x2行显示,5x7点阵,8位数据接口
  251.         write_com(0x0c);                                                //开显示,光标不显示、不闪烁
  252.         write_com(0x06);                                                //光标自增,画面不动
  253.         write_com(0x80);                                                //选择第一行
  254.         write_com(0x01);                                                //清屏
  255. }
  256. void LCD_set_xy( unsigned char x, unsigned char y )//设置LCD显示的位置
  257. {
  258.         unsigned char address;
  259.         if (y == 0)                                                                                                                                                   //y=0为第一行
  260.              address = 0x80 + x;                                 //x=0为一行的第一个
  261.         else                                                                                                                                                                                  //第二行
  262.              address =0xc0+ x;
  263.         write_com(address);                                        //设置数据指针位置
  264. }
  265. void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
  266. //单个字符显示函数
  267. {
  268.         LCD_set_xy( x, y );                                         //设置显示位置
  269.         write_data(dat);                                                //写入待显示数据
  270. }
  271. void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
  272. //字符串显示函数
  273. {
  274.          LCD_set_xy( X, Y );
  275.          while (*s)                                                          //当字符串未到达结尾('\0')时,循环输出单个字符
  276.          {
  277.                  write_data(*s);  
  278.                  s ++;                                                       //指向下一个字符
  279.          }
  280. }
复制代码

所有资料51hei提供下载:
计算器.zip (1.24 MB, 下载次数: 65)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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