基于51单片机的多功能计算器全套设计资料下载(PCB+源码+仿真+论文)

目录

一、实物图

二、资料内容

三、摘要

四、设计要求

五、硬件电路设计

[5.1 单片机电路设计](#5.1 单片机电路设计)

[5.2 键盘电路](#5.2 键盘电路)

5.3蜂鸣器提示电路

5.4液晶显示电路

六、测试验证

6.1整数验证

[6.2 输入出错情况](#6.2 输入出错情况)

七、元器件清单

八、程序

资料下载地址:基于51单片机的多功能计算器全套设计资料下载(PCB+源码+仿真+论文)

一、实物图

二、资料内容

三、摘要

当今社会,随着人们物质生活的不断提高,电子产品已经走进了家家户户,无论是生活或学习,还是娱乐和消遣几乎样样都离不开电子产品,大型复杂的计算能力是人脑所不能胜任的,而且人脑比较容易出错。计算器作为一种快速通用的计算工具方便了用户的使用。计算器可谓是我们最亲密的电子伙伴之一。本设计着重在于分析计算器设计开发过程中的环节和步骤,并从实践经验出发对计算器设计做了详细的分析和研究。

本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用5×8矩阵键盘,可以进行加、减、乘、除等十几种数字运算,同时支持括号的嵌套使用级浮点数的运算,并在LCD1602上显示操作过程。

本次设计注重设计方法及流程,首先根据原理设计电路,利用keil编程,借助实验开发平台进行仿真实验,进而利用altium designer 制作PCB,最后到焊接元器件,直至调试成功。在设计的同时,特别注重keil软件和altium designer软件的使用方法和技巧以及常用的LCD显示器和矩阵键盘的设计和使用方法。

四、设计要求

1、掌握MCS-51系列某种产品(例如8051)的最小电路及外围扩展电路的设计方法;

2、计算器能实现加、减、乘、除、平方、开方、N次方、开N次方、正弦函数、 余弦函数、正切函数、反正弦、反余弦、反正切、对数运算、阶乘(N<=34)、排列、 组合、累加等十九种功能。

3、支持浮点数运算;

4、较为友好的界面显示,对输入实时显示,对计算结果输出显示;

5、能够具备比较完善的报错系统

五、硬件电路设计

5.1 单片机电路设计

为使单片机正常工作,除电源供电部分外,还需提供晶振电路和复位电路。具体电路如下:

由图可知,9脚外接的是按键复位电路,18,19脚外接的是晶振电路,这样,就构成了单片机正常工作的必备电路。同时,为使P0口正常工作,并增加其带负载能力,P0口需接了上拉电阻。图中EA为外部访问允许,欲使CPU仅访问外部程序存储器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。在这里,STC89C52单片机8k的程序存储器已经够本设计使用,无需外部程序储存器,故EA直接接高电平。

5.2 键盘电路

图是键盘电路,共20个按键,用来实现人机交互和运算表达式的输入,S0~S3、S5~S8、S10~S13、S15~S18共16个按键组成一组4*4的矩阵键盘,行线第一行到第四行分别接在P3.0~P3.3口,列线第一列到第四列分别接在P3.4~P3.7口,这样P3口就完成了对4*4的矩阵键盘的接线。同时,注意到按键数量还达不到要求,故增加了四个独立按键S4,S9,S14,S19。他们依次接在P20~P23口。可见,矩阵键盘相对来讲更节省I/O口,但本着学习的目的,加之本设计并不需要太多的I/O口,故为充分学习和利用资源,在这里也设计了4个这样的独立按键。

5.3蜂鸣器提示电路

蜂鸣器主要用于按键时发出声音,提示当前的按键操作,电路如图2.5所示,三极管主要用于驱动蜂鸣器,因为单片机I/O的驱动能力有限。同时单片机I/O口还在这里还起到开关作用,为'0'时打开蜂鸣器通道,使蜂鸣器发声。

5.4液晶显示电路

LCD也是本次设计的重要组成部分之一,主要用于显示输入和输出。电路如图所示,LCD数据端与单片机P0口相连,控制端与P24~P26连接,电位器用于调节对比度。

六、测试验证

6.1整数验证

在此以整数运算为例,介绍计算器的使用方法即流程。首先打开电源,看到LCD打开显示,说明运行正常,接着,输入表达式:12*(56+23)*2,其结果本身应为1896。

输入结束后,点"="按键,即可在第二行显示出运算结果,由图可见运算完全正确。在使用时,可以通过声音开关按钮控制按键音的打开和关闭,在LCD上也有显示,如果再第二行第一个位置没有显示,则没有打开声音,可以通过按钮打开。若有显示,则声音已经打开,可以通过按钮关闭声音。如图所示,此时已经打开声音。

6.2 输入出错情况

由图可以看出,可以进行浮点数运算,还可以从第二行第一个字符,蜂鸣器处于关闭状态。

再按"="号,将会出现出错画面。

七、元器件清单

1)晶振12M一个

(2)stc89c52芯片一片

(3)30pf 2个;10uf 1个;

(4)40脚活动底座一个

(5)LCD液晶一个

(6)按键21个

(7)发光二极管1个

(8)9引脚排阻 1个

(9)680Ω 1个;10k 2个;1k 1个;10k滑动变阻器 1个; 10Ω 1个;

(10) 开关1个

(11) 5V有源蜂鸣器1个

(12) 三极管S8550一个

(13)排针若干,杜邦线若干

八、程序

cpp 复制代码
/*************按键扫描****************************/
char scan()
{

  char h_data,l_data,i,key_num;
  P2=P2&0XE0;//P2低5位送0
  P1=P1|0X0F;//P1低4位送1
  while((P1|0xf0)==0xff)//判断P1低4位是否全为1
  {
   while((P1|0xf0)==0xff);
   DelayMs(10);//延时10ms
  }
   l_data=~(P1|0xf0);//记入列标志
   P2=P2|0X1F;//P2低五位送1
   P1=P1&0XF0;//P1低四位送0
   h_data=~(P2|0xe0);//记入行标志
   for(i=0;i<=4;i++)//计算行号(0~4)
            {
           if(h_data==1)break;
           h_data=h_data>>1;
         }
h_data=i;//行号
  for(i=1;i<=4;i++)//计算列号(1~4)
         {
          if(l_data==1)break;
          l_data=l_data>>1;
        }
l_data=i;//列号
   key_num=h_data*4+l_data;        

  P2=P2&0XE0;//P2低5位送0
  P1=P1|0X0F;//P1低4位送1
  while((P1|0xf0)!=0xff)//判断P1低4位是否全为1
  {
   while((P1|0xf0)!=0xff);
   DelayMs(10);//延时10ms
  }
  return key_num;
}
void float_to_char(float a,char* p)
{
  char i,flag,length;
  flag=0;
  sprintf(p,"%f",a);
  length=strlen (p);
  for(i=0;i<length;i++)
  {
    if(*(p+i)=='.')flag=1;
  }
  if(flag==1)
  for(i=length-1;i>=0;i--)
  {
    if(*(p+i)=='.'){*(p+i)='\0';break;}
    if(*(p+i)!='0'){*(p+i+1)='\0';break;}
  }
}
/**********************更新液晶*************************/
void refresh()//更新液晶
{
  char length,i,j;
  char dot;
  dot=0;
         
  float_to_char(num2,c_num2);//num2转为字符型
  length=strlen(c_num2);
  for(i=0,j=0;i<length;i++)        
  {
    if(c_num2[i]=='.')
        dot=1;
        if(dot==1)
    j++;
  }
  if(j<len)
  {
          if(dot==1)
          {        
            for(i=length;i<(length+len-j);i++)
                 {
                   c_num2[i]='0';
        
                 }
                 c_num2[i]='\0';
          }
          else
                {
                  
                  c_num2[length]='.';
                  if(len-j>1)
                  {
                    for(i=length+1;i<(length+len-j);i++)
                         c_num2[i]='0';
                  }
                  c_num2[length+len-j]='\0';
                }  
  }

  if(neg_flag==1)//'+/-'按下首位加'-'
   {
      length=strlen(c_num2);//计算c_num2长度         
                    for(i=length-1;i>=0;i--)
                  {
                          c_num2[i+1]=c_num2[i];
                  }
                  c_num2[length+1]='\0';
                  c_num2[0]='-';
   }
   
   if(sqrt_flag==1)
           {
      length=strlen(c_num2);//计算c_num2长度
             for(i=length-1;i>=0;i--)
          {
                  c_num2[i+1]=c_num2[i];
          }
          c_num2[length+1]='\0';
          c_num2[0]=0xe8;//字符根号
   }
   
   
   if(error==0)
   {
           float_to_char(num1,c_num1);//num1转为字符型
           WriteCommand(0x01); //显示清屏
           ShowString(0,c_num1);
           ShowString(1,c_num2);  
           ShowChar(15,yun_flag);
   }else
   {
       WriteCommand(0x01); //显示清屏
           ShowString(0,"error!!!");
   }
}
//键值处理
void operation1(char keynum)//按下 '+、-、*、/处理
{
  if(key_last==1)//上次按键为 数字、小数点、+/-、sqrt
   {
     if(neg_flag==1)num2=-num2;//'+/-'按下
         if(sqrt_flag==1)//sqrt按下
         {
         if(num2>=0)
         num2=sqrt(num2);
         else
         error=1;
         }
         if(yun_flag=='+')num1=num1+num2; //按下的是'+'
         if(yun_flag=='-')num1=num1-num2;//按下的是'-'
         if(yun_flag=='*')num1=num1*num2;//按下的是'*'
         if(yun_flag=='/')//按下的是'/'
         {
           if(num2!=0)
           num1=num1/num2;
           else
           error=1;
         }
         num2=0;//num2清零
         sqrt_flag=0;//sqrt_flag清零
     neg_flag=0;//neg_flag清零
         pos_flag=1;//pos_flag回1
   }
   if(keynum==4)yun_flag='+';//yun_flag更新
   if(keynum==8)yun_flag='-';
   if(keynum==12)yun_flag='*';
   if(keynum==16)yun_flag='/';
   len=0;
   key_last=0;//key_last更新   
   refresh();
}
//
void operation2(char keynum)//输入数字
{
  float Data1;
   
  if(keynum==1)Data1=7;//分析输入数字
  if(keynum==2)Data1=8;
  if(keynum==3)Data1=9;
  if(keynum==5)Data1=4;
  if(keynum==6)Data1=5;
  if(keynum==7)Data1=6;
  if(keynum==9)Data1=1;
  if(keynum==10)Data1=2;
  if(keynum==11)Data1=3;
  if(keynum==13)Data1=0;
  if(pos_flag==1)//更新num2
  num2=num2*10+Data1;
  else
  {            
    num2=num2+(Data1/pos_flag);
        pos_flag=pos_flag*10;
        len++;
  }
  key_last=1;//更新key_last        
  refresh();
}

void operation3()//输入小数点
{
  if(pos_flag==1)//首次出现小数点
  {
   pos_flag=pos_flag*10;//小数位权*10
   len++;
  }
  key_last=1;//更新key_last
  refresh();//更新液晶
}
/
void operation4()//输入'='
{
     if(neg_flag==1)num2=-num2;//'+/-'按下
         if(sqrt_flag==1)//sqrt按下
         {
         if(num2>=0)
         num2=sqrt(num2);
         else
         error=1;
         }
         if(yun_flag=='+')num1=num1+num2; //按下的是'+'
         if(yun_flag=='-')num1=num1-num2;//按下的是'-'
         if(yun_flag=='*')num1=num1*num2;//按下的是'*'
         if(yun_flag=='/')//按下的是'/'
         {
           if(num2!=0)
           num1=num1/num2;
           else
           error=1;
         }
         num2=0;//num2清零
         sqrt_flag=0;//sqrt_flag清零
     neg_flag=0;//neg_flag清零
         pos_flag=1;//pos_flag回1
     yun_flag='+';//yun_flag更新
         len=0;
   key_last=0;//key_last更新   
   refresh();
}

void operation5()//输入clear all
{

   num1=0;// num1清零
   num2=0;//num2清零
   sqrt_flag=0;//清sqrt_flag
   neg_flag=0;// 清neg_flag
   pos_flag=1;// Pos_flag=1
   yun_flag='+';// yun_flag(为'+')
   error=0;//清error
   len=0;
   key_last=0;//更新key_flag
   refresh();//更新液晶
}
///
void operation6()//输入'C'
{
num2=0;//num2清零
sqrt_flag=0;//清sqrt_flag
neg_flag=0;//清neg_flag
pos_flag=1;//pos_flag=1
len=0;
key_last=0;//key_last
refresh();//更新液晶
}

void operation7()//输入'+/-'
{
  if(neg_flag==0)//neg_flag反转
  neg_flag=1;
  else neg_flag=0;
  key_last=1;//key_last
  refresh();// 更新液晶
}
/
void operation8()//输入'sqrt'
{
if(sqrt_flag==0)//sqrt_flag反转
  sqrt_flag=1;
else sqrt_flag=0;
key_last=1;//更新key_last
refresh();//更新液晶
}
相关推荐
嵌入式分享11 分钟前
嵌入式分享#41:RK3576改UART波特率【精简版】
linux·嵌入式硬件·ubuntu·嵌入式
典则1 小时前
STM32FreeRtos入门(四)——任务状态和调度
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能天然气火灾监控
stm32·单片机·嵌入式硬件
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能仓库火灾检测系统
stm32·单片机·嵌入式硬件
A9better3 小时前
嵌入式开发学习日志38——stm32之看门狗
stm32·嵌入式硬件·学习
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机智能路灯控制系统
c语言·stm32·单片机·嵌入式硬件·51单片机
A9better14 小时前
嵌入式开发学习日志36——stm32之USART串口通信前述
stm32·单片机·嵌入式硬件·学习
思诺学长14 小时前
BMS(电池管理系统)的主要功能和架构简述
单片机·嵌入式硬件
czhaii14 小时前
全局不关总中断的 RTOS / CosyOS-II for STCAI MCU
单片机
qq_4017004115 小时前
STM32低功耗Tickless模式
stm32·单片机