单片机计算器_单片机计算器实验 - CSDN
精华内容
参与话题
  • 基于51单片机的简易计算器

    万次阅读 多人点赞 2019-01-08 21:17:44
    计算器是以MCS-51系列AT89C51单片机为核心构成的简易计算器系统。该系统通过单片机控制,实现对4*4键盘扫描进行实时的按键检测,并由LCD1602显示屏将过程与结果显示出来。 2.硬件原理图 硬件主要由四部分组成 ...

    1.简介
    本计算器是以MCS-51系列AT89C51单片机为核心构成的简易计算器系统。该系统通过单片机控制,实现对4*4键盘扫描进行实时的按键检测,并由LCD1602显示屏将过程与结果显示出来。
    2.硬件原理图
    在这里插入图片描述
    硬件主要由四部分组成

    • 单片机最小系统
    • 4*4矩阵键盘
    • LCD1602显示屏
    • 系统电源

    3.程序设计
    (1)矩阵键盘驱动程序

    /*------------------------------------------------
             矩阵键盘按键值
      			| 1 | 2 | 3 | + |  
      			| 4 | 5 | 6 | - |  
      			| 7 | 8 | 9 | * |  
      			| 0 | . | = | / | 
      #define KeyPort P1
    
    /*------------------------------------------------
    按键扫描函数,返回扫描键值
    ------------------------------------------------*/
    unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
    {
     unsigned char cord_h,cord_l;//行列值中间变量
     KeyPort=0x0f;            //行线输出全为0
     cord_h=KeyPort&0x0f;     //读入列线值
     if(cord_h!=0x0f)    //先检测有无按键按下
     {
      DelayMs(10);        //去抖
      if((KeyPort&0x0f)!=0x0f)
      {
        cord_h=KeyPort&0x0f;  //读入列线值
        KeyPort=cord_h|0xf0;  //输出当前列线值
        cord_l=KeyPort&0xf0;  //读入行线值
    
        while((KeyPort&0xf0)!=0xf0);//等待松开并输出
    
        return(cord_h+cord_l);//键盘最后组合码值
       }
      }return(0xff);     //返回该值
    }
    /*------------------------------------------------
              按键值处理函数,返回扫键值
               可以根据需要改变返回值
    ------------------------------------------------*/
    unsigned char KeyPro(void)
    {
     switch(KeyScan())
     {
      case 0x7e:return '1';break;//0 按下相应的键显示相对应的码值
      case 0x7d:return '2';break;//1
      case 0x7b:return '3';break;//2
      case 0x77:return '+';break;//3
    
      case 0xbe:return '4';break;//4
      case 0xbd:return '5';break;//5
      case 0xbb:return '6';break;//6
      case 0xb7:return '-';break;//7
    
      case 0xde:return '7';break;//8
      case 0xdd:return '8';break;//9
      case 0xdb:return '9';break;//a
      case 0xd7:return 'x';break;//b
    
      case 0xee:return '0';break;//c
      case 0xed:return '.';break;//d
      case 0xeb:return '=';break;//e
      case 0xe7:return '/';break;//f
      default:return 0xff;break;
     }
    }
    

    (2)LCD1602驱动程序

    #define CHECK_BUSY
    
    sbit RS = P2^4;   //定义端口 
    sbit RW = P2^5;
    sbit EN = P2^6;
    
    #define RS_CLR RS=0 
    #define RS_SET RS=1
    
    #define RW_CLR RW=0 
    #define RW_SET RW=1 
    
    #define EN_CLR EN=0
    #define EN_SET EN=1
    
    #define DataPort P0
    
    /*------------------------------------------------
                  判忙函数
    ------------------------------------------------*/
     bit LCD_Check_Busy(void) 
     { 
    #ifdef CHECK_BUSY
     DataPort= 0xFF; 
     RS_CLR; 
     RW_SET; 
     EN_CLR; 
     _nop_(); 
     EN_SET;
     return (bit)(DataPort & 0x80);
    #else
     return 0;
    #endif
     }
    /*------------------------------------------------
                  写入命令函数
    ------------------------------------------------*/
     void LCD_Write_Com(unsigned char com) 
     {  
     while(LCD_Check_Busy()); //忙则等待
     RS_CLR; 
     RW_CLR; 
     EN_SET; 
     DataPort= com; 
     _nop_(); 
     EN_CLR;
     }
    /*------------------------------------------------
                  写入数据函数
    ------------------------------------------------*/
     void LCD_Write_Data(unsigned char Data) 
     { 
     while(LCD_Check_Busy()); //忙则等待
     RS_SET; 
     RW_CLR; 
     EN_SET; 
     DataPort= Data; 
     _nop_();
     EN_CLR;
     }
    
    /*------------------------------------------------
                    清屏函数
    ------------------------------------------------*/
     void LCD_Clear(void) 
     { 
     LCD_Write_Com(0x01); 
     DelayMs(5);
     }
    /*------------------------------------------------
                  写入字符串函数
    ------------------------------------------------*/
     void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
     {     
           
     while (*s) 
     	{     
     LCD_Write_Char(x,y,*s);     
     s ++;  x++;   
     	}
     }
    /*------------------------------------------------
                  写入字符函数
    ------------------------------------------------*/
    void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
     {     
     if (y == 0) 
     	{     
     	LCD_Write_Com(0x80 + x);     
     	}    
     else 
     	{     
     	LCD_Write_Com(0xC0 + x);     
     	}        
     LCD_Write_Data( Data);  
     }
    /*------------------------------------------------
                  初始化函数
    ------------------------------------------------*/
    void LCD_Init(void) 
    {
    	 LCD_Write_Com(0x38);    /*显示模式设置*/ 
    	 DelayMs(5); 
    	 LCD_Write_Com(0x38); 
    	 DelayMs(5); 
    	 LCD_Write_Com(0x38); 
    	 DelayMs(5); 
    	 LCD_Write_Com(0x38);  
    	 LCD_Write_Com(0x08);    /*显示关闭*/ 
    	 LCD_Write_Com(0x01);    /*显示清屏*/ 
    	 LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
    	 DelayMs(5); 
    	 LCD_Write_Com(0x0C);    /*显示开及光标设置*/
    } 
    

    (3)主函数

    /*------------------------------------------------
                        主程序
    ------------------------------------------------*/
    main()
    {
     unsigned char num,i,sign;                  
     unsigned char temp[16];        //最大输入16个
     bit firstflag;
     float a=0,b=0;
     unsigned char s;
    
     
     LCD_Init();         //初始化液晶屏
     DelayMs(10);        //延时用于稳定,可以去掉
     LCD_Clear();
     LCD_Write_String(0,0," LCD calculator");    //写入第一行信息,主循环中不再更改此信息,所以在while之前写入
     LCD_Write_String(0,1," Fun: + - x / ");    //写入第二行信息,提示输入密码
     while (1)         //主循环
     {
       num=KeyPro();  //扫描键盘
       if(num!=0xff)  //如果扫描是按键有效值则进行处理
       { 
          if(i==0)    //输入是第一个字符的时候需要把改行清空,方便观看
    	  LCD_Clear();
    	 if(('+'==num)|| (i==16) || ('-'==num) || ('x'==num)|| ('/'==num) || ('='==num))//输入数字最大值16,输入符号表示输入结束
    	  {
    	     i=0;  //计数器复位
    	     if(firstflag==0)  //如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
    	     {
    	       sscanf(temp,"%f",&a);
               firstflag=1;
    		 }
    	     else  
    	       sscanf(temp,"%f",&b);
    	     for(s=0;s<16;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
    		    temp[s]=0;
             LCD_Write_Char(0,1,num); 
    	  ///
    	     if(num!='=')      //判断当前符号位并做相应处理
    	       sign=num;      //如果不是等号记下标志位
    	     else
    	     {  
    		    firstflag=0;   //检测到输入=号,判断上次读入的符合
                switch(sign)
    	       {
    		     case '+':a=a+b;
    			 break;
    			 case '-':a=a-b;
    			 break;
    			 case 'x':a=a*b;
    			 break;
    			 case '/':a=a/b;
    			 break;
    			 default:break;
    		   }
    		   sprintf(temp,"%g",a);    //输出浮点型,无用的0不输出
               LCD_Write_String(1,1,temp);//显示到液晶屏
    		   sign=0;a=b=0;            //用完后所有数据清零
    		   for(s=0;s<16;s++)
    		      temp[s]=0;
    		 }
    	  }
         else	if(i<16)
    	 {
    	    if((1==i)&& (temp[0]=='0') )//如果第一个字符是0,判读第二个字符
    	    {
    		  if(num=='.')  //如果是小数点则正常输入,光标位置加1
    		  {
    		    temp[1]='.';
    			LCD_Write_Char(1,0,num);//输出数据
    			i++;
              }           //这里没有判断连续按小数点,如0.0.0 
    		 else
    		 {
    		   temp[0]=num; //如果是1-9数字,说明0没有用,则直接替换第一位0
    		   LCD_Write_Char(0,0,num);//输出数据
    		 }
    	   }
    	   else
    	   {
             temp[i]=num; 
             LCD_Write_Char(i,0,num);//输出数据
    	     i++;   //输入数值累加
    	   }
    	 }
        }	
      }
    }
    

    源码+AD电路图 下载:关注公众号,首页回复“计算器”获取资料
    在这里插入图片描述

    展开全文
  • 基于51单片机计算器设计

    万次阅读 多人点赞 2019-04-22 16:05:21
    能做计算器单片机 单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域,电子、科技、通信、汽车、工业等。本次设计是设计一个简易计算器,能够...

    能做计算器的单片机

    单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域,电子、科技、通信、汽车、工业等。本次设计是设计一个简易计算器,能够进行多位的加减乘除运算。它主要由51单片机的数码管,键盘等模块组成。本计算器是将键盘输入信息经处理通过缓存,送入数码管显示,数码管采用动态扫描方式,计算功能通过软件实现,用C语言对单片机可编芯片进行编程,实现计算器的设计。

    把期中做的作业放上来哈哈

    硬件电路描述

    要进行数据的计算就必须先进行数据的输入,也就必须确定按键输入的数值是什么,这就需要对键盘进行扫描,从而确定究竟是哪个键按下。 对于键盘的扫描,这里采用行列扫描的方法来完成对键盘的扫描。原理就是先确定按键在哪一行,接着再确定是哪一列,这样就可以知道是哪个按键被按下了。我是将P3口作为按键扫描口的,比如,先使行线输出全“0”,读列线,再使列线输出全为“0”,读行线。两次结果再相与,则得到一个值为键值。同理,每个按键都会有一个对应的十六进制值,把它们列出来进行一一对应就行了。如下图。
    在这里插入图片描述

    程序设计描述

    1.程序总流程图
    在这里插入图片描述
    2.编程思路
    在单片机接通电源后,单片机就会一直重复检测键盘上的按钮是否被按下。如果有键被按下,就会进入选择判断,当按下数字键,相应数字计入变量keynum中并在数码管上移位显示;当按下运算符键和特殊功能键,也将对应的10到15数字计入到keynum中并进行第二次判断,如果keynum是0~9,则将数据变量dat×10加上keynum;如果是10(加号对应值),进入加法程序(加法标识变量加1,其他运算符标识变量归零,把dat赋值给另一变量datA;当法标识变量大于1时,就是连加,需要将dat等于dat加上datA的值)。其他运算符也是差不多的程序。keynum等于14,就进入等于运算程序。这个程序中也就是四个if语句,如果运算符变量为1就运行相应代码。如加法运算符为1,则使dat加上datA的值赋给dat。最后将dat放入显示程序中显示,而无论何时按下keynum等于15时,所有状态清零。这就是我写的代码的主要思路。

    源代码及注释

    #include <reg51.h>
    #define long unsigned long
    #define KEYPORT P3
    sbit beep=P1^4;
    bit dot;
    typedef unsigned char byte;
    
    long dat;       //数据
    long datA;      //过度数据
    byte addflag;   //加法标志位
    byte subflag;   //减法标志位
    byte mulflag;   //乘法标志位
    byte divflag;   //除法标志位
    byte clrflag;   //数据处理标志位
    byte scanok;
    int checkok;
    int keynum;    //按键键值
    static byte dispbuf[6];
    //数码管字段表
    sbit duan=P2^6;
    sbit wela=P2^7;
    unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                            0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    //变量定义
    
    void delayms(int ms)//这个软件大约可以等待ms毫秒
    {
    	  int i,k;
    	  for(k=0; k<ms;k++)	{   for(i=0;i<50;i++);  }
    }
    
    
    /*---------------------------------------------------------------
    查询是否有键按下,有键按下返回键值,无键按下则返回0xff
    ---------------------------------------------------------------*/
    byte keysearch(void)
    {
    	byte k;
     	KEYPORT=0xf0;
     	k=KEYPORT;
     	KEYPORT=0x0f;
     	k=KEYPORT|k;
     	scanok=1;return k;
    }
    void HEX_TO_BCD(int num)
    {	dispbuf[5]  = num%1000000/100000;
        dispbuf[4]  = num%100000/10000;
        dispbuf[3]  = num%10000/1000;
        dispbuf[2]  = num%1000/100;
        dispbuf[1]  = num%100/10;
        dispbuf[0]  = num%10;
    }
    /*---------------------------------------------------------------
    显示子程序
    轮流导通各位数码管,再送出字段码
    延时显示一段时间后再继续导通下一位
    ---------------------------------------------------------------*/
    void scandisp(void)       
    {
    	byte posi=0x1f,i,temp;
    	//posi,为position的缩写,指显示哪一个8字
    	for(i=0;i<6;i++)
     	{
        	temp= dispbuf[i];         //显示缓存区数据查表
        	temp= table[temp];
        	if(i==2&&dot)temp|=0x80;  //i是小数点位置,变量dot=1,点亮小数点
        	P0 = 0;	     duan=1;   duan=0;//先关闭数码管,再切换
        	P0 = posi;   wela=1;   wela=0;  	
        	P0 = temp;   duan=1;   duan=0;
        	delayms(5);//延时 
        	posi>>=1;  posi|=0x20;    //循环右移
     	}
    }
    
    /*---------------------------------------------------------------
    移位显示子程序
    把显示数组中的最低3位赋给高3位,使最新输入的键盘值赋给数组的最低位
    输入:键值
    返回:无
    ---------------------------------------------------------------*/
    void digitin(byte val)               
    { 
    	dispbuf [3]= dispbuf [2];
     	dispbuf [2]= dispbuf [1];
    	dispbuf [1]= dispbuf [0];
     	dispbuf [0]= val;
    }
    
    /*---------------------------------------------------------------
    扫描得到的键值和实际需要的键盘任务的转换函数
    也叫键盘码散转程序
    输入:键值,有0x00~0xff钟可能性,根据显示的键值可以修改此函数
    返回:无
    ---------------------------------------------------------------*/
    void keybranch(byte k)          
    {	if(scanok)
       {scanok=0;
    	switch(k)
     	{
     	    case 0x00:break;
         	case 0xee:keynum=1;break;
         	case 0xde:keynum=2;break;
         	case 0xbe:keynum=3;break;
         	case 0xed:keynum=4;break;
         	case 0xdd:keynum=5;break;
        	case 0xbd:keynum=6;break;
         	case 0xeb:keynum=7;break;
         	case 0xdb:keynum=8;break;
         	case 0xbb:keynum=9;break;
         	case 0xd7:keynum=0;break;
    		case 0x7e:keynum=10;break;//加法
    		case 0x7d:keynum=11;break;//减法
    		case 0x7b:keynum=12;break;//乘法
    		case 0x77:keynum=13;break;//除法
    		case 0xb7:keynum=14;break;//等于
    		case 0xe7:keynum=15;break;//清零
         	default:break;
     	 } checkok=1;
    } }
    /*---------------------------------------------------------------
    处理程序,键值为15时或者清除标志为1时,数据清零
    ---------------------------------------------------------------*/
    void datchuli(void)
    {if(keynum==15)
      {
       dat=0;  datA=0;
       HEX_TO_BCD(dat);
      }
    else if(clrflag)                    //清除标志为1,则执行以下。
      {        
       dat=0;
       clrflag=0;                 //为下次使用准备。
       HEX_TO_BCD(dat);
      }
      if(keynum<10)
      {
      digitin(keynum);
      dat=dat*10+keynum;
      }
    }
    
    void add(void)
    {
       addflag++;                          //加法标志置1。。。
       subflag=mulflag=divflag=0;          //将其它运算标志清零。。(一次只能作一种运算)
       clrflag=1;                          //清零标标置1,(当按下加号后,再按第二个加数时,这时应该显示第二加数。。所以要清掉第一个加数。)
       if(addflag>1)
       {
       dat=datA+dat;
       datA=dat;
       }
       datA=dat;
    }
    void sub(void)						   //减法
    { subflag++;
      addflag=mulflag=divflag=0;
      clrflag=1;
      if(subflag>1)
      {
      dat=datA-dat;
      datA=dat;
      }
      datA=dat;
    }
    void mul(void)							//chengfa
    { mulflag++;
      addflag=subflag=divflag=0;
      clrflag=1;
      if(mulflag>1)
      {
      dat=dat*datA;
      datA=dat;
      }
      datA=dat;
    }
    void div(void)							//chufa
    { divflag++;
      addflag=subflag=mulflag=0;
      clrflag=1;
      if(divflag>1)
      {
      dat=datA/dat;
      datA=dat;
      }
      datA=dat;
    }
    void equ(void)
    {
     
       if(addflag)                           //如果些时做加法运算。。
       {
       dat=dat+datA;                     //计算各存入dat(显示程序会将dat显示的。。)
       }
       if(subflag)
       {
       dat=datA-dat;
       }
       if(mulflag)
       {
       dat=datA*dat;
       }
       if(divflag)
       {
       dat=datA/dat;
       }
       addflag=subflag=mulflag=divflag=0;//运算一次完成后将所有运标志清零。为下次运算作准备。。
       HEX_TO_BCD(dat);	clrflag=1;
    }
    void calculate_handle(void)//计算函数。。
    {	
     if(checkok)//如果检测键值完。则执行以下。
     {
      checkok=0;//检测完标志清零..
      switch (keynum)//如果是+,-,*,/,=则进入相应的函数。。
      {
       case 10 : {add();HEX_TO_BCD(dat);} break;    //如果是按了"+",则进入加法函数。
       case 11 : {sub();HEX_TO_BCD(dat);} break;    //如果是按了"-",则进入减法函数。
       case 12 : {mul();HEX_TO_BCD(dat);} break;    //如果是按了"*",则进入乘法函数。
       case 13 : {div();HEX_TO_BCD(dat);} break;    //如果是按了"/",则进入除法函数。
       case 14 : equ(); break;    //如果是按了"=",则进入等于函数。
       default : datchuli();       //如果不是,计算符(即为数字),则进入数据处理函数。
      }
    
     }}
    /*---------------------------------------------------------------
    主函数:将4X4键盘的键值显示在数码管上
    ---------------------------------------------------------------*/
    void main(void)
    {
    	byte k;
    	while(1)
     	{
     		k=keysearch();
    		
    		if(k!=0xff)   
        {
        	delayms(10);//有键按下
        	k=keysearch();
    		keybranch(k);
      		do
    		{
      			k=keysearch();
    			scandisp();
      		} while(k!=0xff);      //等待键释放
         }
    	 calculate_handle();
    	 scandisp();
      }
    }
    
    

    设计体会

    一开始只是会矩阵键盘和LCD扫描显示,所以当时是想做一个计算器应该还是挺容易的,但直到真正开始做的时候,才发现并不简单。一开始,想的就是,把运算键前输入的数值存到一个变量,后面的数值存到另一个变量内,然后再运算。但问题就来了,如何让单片机知道两次输入的数值要存到不同的变量去?如何把这些变量分别显示到显示管上?然后就要引入更多的变量、设计更多的函数。做出来的第一个版本,能实现加减乘除了,但还有一些问题。按下运算符时,数码管就会直接清零,不像真正计算器那样,按下运算符数码管上数值先不变,等下一数值输入时才变。还有不能实现连续运算的问题,最后还是修改好了。总的来说,这次设计的过程是很有挑战的,尤其对于我这种不善于编程的人来讲,遇到的问题,虽说比较麻烦,但还是车到山前必有路

    展开全文
  • 本程序实现了完整版计算器,包括加减乘除、带小数点显示、带小数点输入、此外还有带时钟功能。当然也可以实现函数功能,只是东西太多了,放不开了。。就没有加上。以后在上传吧.带仿真文件的,一定要用Proteus7.8...
  • 基于51单片机的简易计算器制作

    万次阅读 2018-05-08 23:16:13
    基于51单片机的简易计算器制作 51单片机可以实现的功能很多,今天笔者介绍一种使用4*4矩阵键盘和八位共阴数码制作的简易计算器。数码管使用的是CL3641AH。原理图如下: S15 S11 S7 S3分别是4,5,6,- S14 S10 S6 ...

    基于51单片机的简易计算器制作

    51单片机可以实现的功能很多,今天笔者介绍一种使用4*4矩阵键盘和八位共阴数码制作的简易计算器。数码管使用的是CL3641AH。原理图如下:捕获

    捕获

    S15 S11 S7 S3分别是4,5,6,-
    S14 S10 S6 S2分别是7,8,9,*
    
    /*  S16 S12 S8 S4分别是1,2,3,+
    
    ​```
    S15 S11 S7 S3分别是4,5,6,-
    S14 S10 S6 S2分别是7,8,9,*
    S13 S9 S5 S1分别是0,CLR,=,/
    ​```
    
    */
    
    /* 可以实现两个数运算,每个数至多八位  */
    
    # include<reg52.h>
    
    typedef unsigned char uint8;
    typedef unsigned int uint16;
    
    sbit rw=P2^5;
    sbit rs=P2^6;
    sbit e=P2^7;
    sbit led=P3^7;
    
    sbit beep=P2^0;
    uint8 key,num;
    uint8 fuhao;//定义那个具体的符号是加减还是乘除
    uint8 flag; //定义有没有按下符号按键,这个是统称
    long a,b,c,d;   //定义运算数据的第一个和第二个及等于的数变量
    uint8 k; //定义小数点后面显示的位数
    uint8 biao;
    
    uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存显示的数据
    
    void delay(uint16 i)
    {
    
    ​```
    while(i--);
    ​```
    
    }
    void lcdwrc(uint8 c)
    {
    
    ​```
    delay(1000);
    rs=0;
    rw=0;
    e=0;
    P0=c;
    e=1;
    delay(1000);
    e=0;
    ​```
    
    }
    void lcdwrd(uint8 dat)
    {
    
    ​```
    delay(1000);
    rs=1;
    rw=0;
    e=0;
    P0=dat;
    e=1;
    delay(1000);
    e=0;
    rs=0;
    ​```
    
    }
    
    void lcdinit()
    {
    
    ​```
    delay(1500);
    lcdwrc(0x38);
    delay(500);
    lcdwrc(0x38);
    delay(500);
    lcdwrc(0x38);
    delay(500);
    lcdwrc(0x38);
    lcdwrc(0x08);
    lcdwrc(0x01);
    lcdwrc(0x06);
    lcdwrc(0x0c);
    key=0;
    num=0;
    flag=0;
    fuhao=0;
    a=0;
    b=0;
    c=0;
    d=0;
    biao=0;
    led=0;
    ​```
    
    }
    
    void keyscan()
    {
    
    ​```
    P1=0xfe;   //定义第一行为零,然后判断哪一列按下
    if(P1!=0xfe)
    {
        delay(1000);
        if(P1!=0xfe)
        {
            key=P1&0xf0;
            switch(key)
            {
                case 0xe0: num=0;break;   //1
                case 0xd0: num=1;break;   //2
                case 0xb0: num=2;break;   //3
                case 0x70: num=3;break;   //¼Ó
            }
        }
        while(P1!=0xfe);
        if(num==0||num==1||num==2)   //确认第一行的数1,2,3
        {
            if(flag==0)  //没有按下符号建
            {
                //led=1;
                a=a*10+dat1[num];   
            }
            else
            {
                //led=1;
                b=b*10+dat1[num];
            }
    
        }
        if(num==3)
        {
            //led=0;
            flag=1;
            fuhao=1;//加号
        }
        lcdwrd(0x30+dat1[num]);
    }
    ​```
    
    ​```
    P1=0xfd;                //令第二行为零,然后判断第几行按下
    if(P1!=0xfd)
    {
        delay(1000);
        if(P1!=0xfd)
        {
            key=P1&0xf0;
            switch(key)
            {
                case 0xe0: num=4;break;   //4
                case 0xd0: num=5;break;   //5
                case 0xb0: num=6;break;   //6
                case 0x70: num=7;break;   //减-
            }   
        }
        while(P1!=0xfd);
        if(num==4||num==5||num==6)
        {
            if(flag==0)  //没有按下符号建
            {
                //led=1;
                a=a*10+dat1[num];   
            }
            else
            {
                //led=1;
                b=b*10+dat1[num];
            }           
        }
        else
        {
            flag=1;
            fuhao=2;//´代表减号
        }
        lcdwrd(0x30+dat1[num]);
    }
    ​```
    
    ​```
    P1=0xfb;         //令第三行为零,然后判断第几列按下
    if(P1!=0xfb)
    {
        delay(1000);
        if(P1!=0xfb)
        {
            key=P1&0xf0;
            switch(key)
            {
                case 0xe0: num=8;break;   //7
                case 0xd0: num=9;break;   //8
                case 0xb0: num=10;break;  //9
                case 0x70: num=11;break;  //乘*
            }   
        }
        while(P1!=0xfb);
        if(num==8||num==9||num==10)
        {
            if(flag==0)  //没有按下符号键
            {
                //led=1;
                a=a*10+dat1[num];   
            }
            else
            {
                //led=1;
                b=b*10+dat1[num];
            }           
        }
        else
        {
            flag=1;
            fuhao=3;//代表乘号
        }
        lcdwrd(0x30+dat1[num]);
    }
    ​```
    
    ​```
    P1=0xf7;         //另第四行为零,然后判断第几列按下
    if(P1!=0xf7)
    {
        delay(1000);
        if(P1!=0xf7)
        {
            key=P1&0xf0;
            switch(key)
            {
                case 0xe0: num=12;break;  //0
                case 0xd0: num=13;break;  //清楚rst
                case 0xb0: num=14;break;  //等号=
                case 0x70: num=15;break;  //除/
            }   
        }
        while(P1!=0xf7);
        switch(num)
        {
            case 12: 
                    if(flag==0)  //没有按下符号键
                    {
                        //led=1;
                        a=a*10+dat1[num];
                        lcdwrd(0x30);   
                    }
                    else
                    {
                        //led=1;
                        b=b*10+dat1[num];
                        lcdwrd(0x30);
                    }
                    break;
    
            case 13: 
                    lcdwrc(0x01);   //清屏指令      
                    a=0;
                    b=0;
                    flag=0;
                    fuhao=0;
                    break;
    
            case 15:
    
                    flag=1;
                    fuhao=4;
                    lcdwrd(0x2f);//除号/
                    break;
    
            case 14: 
                    if(fuhao==1)//加
                    {
                        lcdwrc(0x4f+0x80);
                        lcdwrc(0x04);//设置光标左移¯,屏幕不移动
                        c=a+b;
                        while(c!=0)  //一位一位显示
                        {
                            lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
                            c=c/10;//取前面的结果数据   
                        }
                        lcdwrd(0x3d); //显示等于号=
                        a=0;
                        b=0;
                        flag=0;
                        fuhao=0;//全部清除为零
                    }
                    if(fuhao==2)   //减
                    {
                        lcdwrc(0x4f+0x80);
                        lcdwrc(0x04);//设置光标左移,屏幕不移动
                        if(a>b)
                            c=a-b;
                        else
                            c=b-a;
    
                        while(c!=0)  //一位一位的显示
                        {
                            lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
                            c=c/10;//取前面的结果数据   
                        }
                        if(a<b) lcdwrd(0x2d); //显示减号-
                        lcdwrd(0x3d); //显示等号=
                        a=0;
                        b=0;
                        flag=0;
                        fuhao=0;//全部清除为零
                    }
    
                    if(fuhao==3)//乘法        
                    {
                        lcdwrc(0x4f+0x80);
                        lcdwrc(0x04);//设置光标左移,屏幕不移动
                        c=a*b;
                        while(c!=0)  //一位一位的显示
                        {
                            lcdwrd(0x30+c%10);//显示结果的位置在0x4f的位置
                            c=c/10;//取前面的结果数据   
                        }
                        lcdwrd(0x3d); //显示等于号=
                        a=0;
                        b=0;
                        flag=0;
                        fuhao=0;//全部清除为零    
                    }
                    if(fuhao==4)
                    {
                        k=0;
                        lcdwrc(0x4f+0x80);
                        lcdwrc(0x04);//设置光标左移,屏幕不移动
                        c=(long)(((float)a/b)*1000);//强制转化为long
                        while(c!=0)  //一位一位的显示
                        {
                            k++;
                            lcdwrd(0x30+c%10);//显示接轨的最后一位在0x4f的位置
                            c=c/10;//取前面的结果数据
                            if(k==3)
                            {
                                lcdwrd(0x2e);
                                k=0;
                            }       
                        }
                        if(a/b<0)     //如果a比b小的话那么除的结果最高位是零
                        {
                            lcdwrd(0x30);   
                        }
                        lcdwrd(0x3d); //显示等号
                        a=0;
                        b=0;
                        flag=0;
                        fuhao=0;//全部清除为零
                    }
                    break;
    
        }
    }
    ​```
    
    }
    
    
    
    void main()
    {
    
    ​```
    lcdinit();
    while(1)
    {
        keyscan();  
    }
    ​```
    
    }
    
    展开全文
  • 单片机简易计算器全套(源程序、hex文件、Proteus仿真、设计报告) 包含8套不同的简易计算器的代码。
  • 单片机实现计算器功能

    千次阅读 2018-03-04 23:22:07
    #include &lt;reg51.h&gt;sbit E=P2^2;sbit RS=P2^0;sbit RW=P2^1;#define GPIO_KEY P1unsigned char KeyValue=17; //键盘按键值void KeyDown(void); //键盘扫描void delay1ms(unsigned int x);...
    #include <reg51.h>
    sbit E=P2^2;
    sbit RS=P2^0;
    sbit RW=P2^1;
    #define GPIO_KEY P1
    unsigned char KeyValue=17;  //键盘按键值
    void KeyDown(void);   //键盘扫描
    void delay1ms(unsigned int x);
    void init();      //lcd1602初始化
    void writecom(unsigned char j);   //写命令
    void writedata(unsigned char j);   //写数据
    void fbusy(); //忙检测
    unsigned char LEDBuffer[5];


    unsigned char i=0;           //x作为第一个数据   注意char型的数据位数只有8位,最高计数到256
    unsigned char flag=0;
    unsigned int result=0,temp=0,x;
    unsigned int numbuffer[10];   //用于缓存数据
    unsigned int j=0;
    unsigned char pflag=0,mflag=0,hflag=0,lflag=0;     //用于定义乘除法的优先级
    void main()
    {
    IT0=1;   //定义外部中断用于清屏
    EX0=1;
    EA=1;
        SP=0x50;
    init();
    writecom(0x80);
    writedata('1');
    writedata('5');
    writedata('0');
    writedata('0');
    writedata('9');
    writedata('0');
    writedata('5');
    writedata('1');
    writedata('3');
    writedata('0');
    writedata(' ');
    writedata(' ');
    writedata('m');
    writedata('c');
    writedata('l');
    delay1ms(500);
    init();   
    writecom(0x80);
    while(1)
    {
    //    writecom(0x80);
       KeyDown();
      
    switch(KeyValue)
    {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
      case 9:{
          writedata('0'+KeyValue);
      temp=temp*10+KeyValue;      //第一个数字
      KeyValue=17;
      }
      break;
      case 10:{
          writedata('+');
      numbuffer[j]=temp;   //缓存区数据
      temp=0;
      j++;
                   if(pflag)
      {
          numbuffer[j-2]=numbuffer[j-1]*numbuffer[j-2];
      numbuffer[j-1]=0;
      j--;
      pflag=0;
    }
    if(mflag)
      {
          numbuffer[j-2]=numbuffer[j-2]/numbuffer[j-1];
      numbuffer[j-1]=0;
      j--;
      mflag=0;
    }
    if(hflag)
      {
          numbuffer[j-1]=-1*numbuffer[j-1];
      hflag=0;
    }
    if(lflag)
      {
          numbuffer[j-2]=numbuffer[j-2]%numbuffer[j-1];
      j--;
      lflag=0;
    }
      KeyValue=17;
      flag=1;    //定义一个加法的标志位
      }
      break;
      case 11:{
          writedata('-');
      numbuffer[j]=temp;   //缓存区数据
      j++;
      temp=0;
                   if(pflag)
      {
          numbuffer[j-2]=numbuffer[j-2]*numbuffer[j-1];
      j--;
      pflag=0;
    }
    if(mflag)
      {
          numbuffer[j-2]=numbuffer[j-2]/numbuffer[j-1];
      j--;
      mflag=0;
    }
    if(hflag)
      {
          numbuffer[j-1]=-1*numbuffer[j-1];
      hflag=0;
    }
    if(lflag)
      {
          numbuffer[j-2]=numbuffer[j-2]%numbuffer[j-1];
      j--;
      lflag=0;
    }
    hflag=1;
      KeyValue=17;
      flag=2;
      }
      break;
      case 12:{
          writedata('*');
      numbuffer[j]=temp;   //缓存区数据
      j++;
      if(pflag)
      {
          numbuffer[j-2]=numbuffer[j-1]*numbuffer[j-2];
      numbuffer[j-1]=0;
      j--;
      pflag=0;
    }
    if(mflag)
      {
          numbuffer[j-2]=numbuffer[j-2]/numbuffer[j-1];
      numbuffer[j-1]=0;
      j--;
      mflag=0;
    }
    if(hflag)
      {
          numbuffer[j-1]=-1*numbuffer[j-1];
      hflag=0;
    }
    if(lflag)
      {
          numbuffer[j-2]=numbuffer[j-2]%numbuffer[j-1];
      j--;
      lflag=0;
    }
      temp=0;
      pflag=1;     //定义乘除法的高优先级
      KeyValue=17;
      flag=3;
      }
      break;
      case 13:{
          writedata('/');
      numbuffer[j]=temp;   //缓存区数据
      j++;
      if(pflag)
      {
          numbuffer[j-2]=numbuffer[j-1]*numbuffer[j-2];
      numbuffer[j-1]=0;
      j--;
      pflag=0;
    }
    if(mflag)
      {
          numbuffer[j-2]=numbuffer[j-2]/numbuffer[j-1];
      numbuffer[j-1]=0;
      j--;
      mflag=0;
    }
    if(hflag)
      {
          numbuffer[j-1]=-1*numbuffer[j-1];
      hflag=0;
    }
    if(lflag)
      {
          numbuffer[j-2]=numbuffer[j-2]%numbuffer[j-1];
      j--;
      lflag=0;
    }
      temp=0;
      mflag=1;
      KeyValue=17;
      flag=4;
      }
      break;
      case 14:{
          writedata('%');
      numbuffer[j]=temp;   //缓存区数据
      j++;
      temp=0;
                   lflag=1;  //求余优先级
      KeyValue=17;
      flag=5;
      }
      break;
      case 15:{
          writedata('=');
      numbuffer[j]=temp;   //缓存区数据
      temp=0;
      j++;   
      if(pflag)
      {
          numbuffer[j-2]=numbuffer[j-2]*numbuffer[j-1];
      j--;
      j--;   
      pflag=0;
    }
    if(mflag)
      {
          numbuffer[j-2]=numbuffer[j-2]/numbuffer[j-1];
      j--;
      j--;
      mflag=0;
    }


    if(hflag)
      {
          numbuffer[j-1]=-1*numbuffer[j-1];
      hflag=0;
    }
    if(lflag)
      {
          numbuffer[j-2]=numbuffer[j-2]%numbuffer[j-1];
      j--;
      j--;
      lflag=0;
    }
      KeyValue=17;
                   for(i=0;i<=j;i++)
      {
          result+=numbuffer[i];
    }
    i=0;
    while(result)
             {
                LEDBuffer[i]=result%10;    //将数据存储在缓存区中
            result/=10;
            i++; //i的值比实际位数多一个值
             }
     for(i;i>0;i--)
     {
        writedata('0'+LEDBuffer[i-1]);   //显示输出结果
     }
    }
      break;
    }
    }
    }


    void init()
    {
        writecom(0x01);
    writecom(0x38);
    writecom(0x0c);
    writecom(0x06);
    }
    void writecom(unsigned char j)
    {
    fbusy();
        E=0;
    RS=0;
    RW=0;
    E=1;
    P0=j;
    E=0;
    }
    void fbusy()
    {    
    E=0;
        P0=0xff;
    RS=0;
    RW=1;
    E=1;
    while(P0&0x80)
    {
      E=0;
      E=1;
    }
    }
    void writedata(unsigned char j)
    {
    fbusy();
    E=0;
    RS=1;
    RW=0;
    E=1;
    P0=j;
    E=0;


    }
    void KeyDown(void)  //键盘扫描
    {
    char a=0;
    GPIO_KEY=0x0f;
    if(GPIO_KEY!=0x0f)         //读取按键是否按下
    {
    delay1ms(10);          //延时10ms进行消抖
    if(GPIO_KEY!=0x0f)    //再次检测键盘是否按下
    {

    //测试列
    GPIO_KEY=0X0f;
    switch(GPIO_KEY)
    {
    case(0X07): KeyValue=0;break;
    case(0X0b): KeyValue=1;break;
    case(0X0d): KeyValue=2;break;
    case(0X0e): KeyValue=3;break;
    }
    //测试行
    GPIO_KEY=0Xf0;
    switch(GPIO_KEY)
    {
    case(0X70): KeyValue=KeyValue;break;
    case(0Xb0): KeyValue=KeyValue+4;break;
    case(0Xd0): KeyValue=KeyValue+8;break;
    case(0Xe0): KeyValue=KeyValue+12;break;
    }
    while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
    {
    delay1ms(10);
    a++;
    }
    }
    }
    }
    void delay1ms(unsigned int x)
    {
       unsigned int i,j;
       for(i=0;i<x;i++)
         for(j=0;j<120;j++);
    }
    void init1(void) interrupt 0
    {
         for(i=0;i<=4;i++)
    {
    LEDBuffer[i]=0;         //清空数组中的数据
    }
    for(i=0;i<=8;i++)
    {
    numbuffer[i]=0;         //清空数组中的数据
    }    
     result=0;
     i=0;
     x=0;
     temp=0;
          init();
          writecom(0x80);
    }
    展开全文
  • 【C51单片机】简易计算器设计(仿真)

    千次阅读 多人点赞 2020-08-17 21:19:38
    设计一个简易计算器,模拟常见计算器的加减乘除运算功能,通过1602液晶屏来显示数字、4*4的矩阵按键来模拟计算机的按键, 2、PROTEUS中设计的电路图 3、源代码 #include <reg51.h> #include <...
  • 单片机计算器课程设计,有报告的,总共花了好几天才完成的,共享一下,多多指教!
  • 新手教程,基于51单片机的计算机例程,亲测有效,51单片机是对所有兼容Intel 8031指令系统的单片机的统称。该系列单片机的始祖是Intel的8004单片机,后来随着Flash rom技术的发展,8004单片机取得了长足的进展,成为...
  • 在51单片机上实现的完整功能的计算器源代码 单片机 , 计算器 , 源代码
  • 基于51单片机的简单计算器

    千次阅读 多人点赞 2018-06-06 19:58:31
    在上一篇中,我们已经说过了基于51单片机的简单拨号器,在下边,我们将写一个计算器程序,原理很简单,只需要在拨号器的基础上,算出拨号器所表示的数字,并进行计算即可。 代码如下; #include"reg51.h&...
  • 运用51单片机制作计算器的源代码@TOC /* S16 S12 S8 S4分别是123+ S15 S11 S7 S3分别是456- S14 S10 S6 S2分别是789* S13 S9 S5 S1分别是0 CLR = / */ /* 实现两个数的运算,每个数的位数至少可以八位 */ #include&...
  • 51单片机汇编计算器

    2020-07-29 14:20:48
    计算器,实现简单计算功能,用的是汇编代码写的
  • 绝对正确的51单片机简易计算器程序,#include #include #include<string.h>
  • 基于51单片机计算器 C语言程序

    千次阅读 2011-07-07 13:28:44
    对于 电子这个专业,虽不打算以后吃这晚饭,但是期末作业还是得做——“一个简单的计算器程序”。由于时间,一直没顾得上整理,今天就把它贴这儿给大家分享,也全当做是对自己这美好青春时光的一点儿记忆吧......嘻...
  • 51单片机计算器的编写及实现

    千次阅读 2017-12-25 08:44:25
    code:/* S16 S12 S8 S4分别是123+ S15 S11 S7 S3分别是456- S14 S10 S6 S2分别是789* S13 S9 S5 S1分别是0 CLR = / */ /* 实现两个数的运算,每个数的位数至少可以八位 */ #include typedef unsigned char ...
  • 基于51单片机的科学计算器,可实现加减乘除·,带括号运算,开根号,三角函数,对数函数,乘方。
  • 使用6位数码管显示,可以实现加减乘除,当计算结果超过所能显示的位数时,显示错误。
  • 可实现两位整数的加减乘除用数码管显示
  • 基于51单片机计算器Proteus仿真:资源包含原理图,源程序及文档。
1 2 3 4 5 ... 20
收藏数 1,868
精华内容 747
关键字:

单片机计算器