单片机简易计算器.docx
《单片机简易计算器.docx》由会员分享,可在线阅读,更多相关《单片机简易计算器.docx(12页珍藏版)》请在冰豆网上搜索。
单片机简易计算器
单片机应用于简易计算器的仿真实验
班级学号:
1411050123
姓名:
何盟
目录
一.课程设计的目的和要求2
1.课程设计的目的2
2.课程设计要求2
二.总体设计2
1.基本工作原理2
2.系统组成单元2
三.硬件设计键盘输入部分3
四.软件设计4
五.操作说明9
六.参考文献9
一.课程设计的目的和要求
1.课程设计的目的
首先,综合运用单片机原理与接口技术课程中所学到的理论知识来独立完成此次设计课题,培养我们查阅手册和文献资料的良好习惯,以及培养我们独立分析和解决实际问题的能力。
其次,在学习了理论知识的基础上进一步熟悉常用电子器件的类型和特征,并掌握合理选用的原则。
再次,就是学会电子电路的安装与调试技能,以及与同组的组员的团结合作的精神。
2.课程设计要求
利用89c51作为主控器组成一个四则运算的计算器。
二.总体设计
1.基本工作原理
本设计利用AT89C51单片机来控制液晶显示器和矩阵式键盘,实现了简易的计算器功能。
通过键盘输入需要计算的计算式子,该式子会显示在液晶的第一行,当键入等于号后,计算结果会显示在液晶的第二行。
本设计中液晶选用1602字符型液晶显示器,显示参与运算的数字以及最终的运算结果,键盘采用4*4矩阵式键盘。
本计算器是以80C51单片机为核心构成的简易计算器系统。
该系统通过单片机控制,实现对4*4键盘扫描进行实时的按键检测,并把检测数据和计算结果存储下来,显示在LCD液晶显示器上,并可实现清零。
2.系统组成单元
中央处理单元
CPU选用AT89C—51对整个系统进行控制:
它将数据输出到显示屏,实现键入、输出的显示;根据键盘输入调用相应键处理子程序,实现数据的计算;单片机的管脚如下所述:
AT89C51的管脚分布如下:
VCC:
供电电压。
GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流。
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
/PSEN:
外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出。
电源电路部分
在各种电子设备中,直流稳压电源是必不可少的组成部分,它是电子设备唯一能量来源,它的设计思路是根据我们以前学过的模电电子技术,要想得到我们所要的+6V输出电压,就需将交流220V的电压经过变压器、整流电路、滤波电路和稳压电路四个部分。
LCD输出显示部分
1602采用标准的16脚接口,其管脚功能介绍如下:
1:
VSS为电源地
2:
VDD接5V电源正极
3:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高。
4:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
5:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
6:
E(或EN)端为使能(enable)端。
7~14:
D0~D7为8位双向数据端。
15~16:
空脚或背灯电源。
15脚背光正极,16脚背光负极
。
三.硬件设计键盘输入部分
矩阵式键盘由行线和列线组成,按键位于行和列的交叉点上,很明显,在所需按键数量较多时能节省很多的I/O口。
如图所示为简易计算器的电路原理图。
简易计算器电路原理图
系统选用的主要元器件有:
单片机(AT89C51),LCD显示器(1602),按钮开关(SW-PB),排阻(9管脚,1k),电阻、电容、晶振、发光二极管等若干。
四.软件设计
该计算器系统的软件设计分为以下几个模块:
(1)主程序模块,
(2)键盘扫描及识别子程序,(3)显示子程序,(4)计算程序。
主程序流程图如下:
总程序框图如下:
总程序如下:
can()//键盘扫描程序
{P3=0xfe;if(P3!
=0xfe)
{delay(20);延迟20msif(P3!
=0xfe)
{temp=P3&0xf0;
switch(temp)
{case0xe0:
num=0;break;
case0xd0:
num=1;break;
case0xb0:
num=2;break;
case0x70:
num=3;break;
}
}
while(P3!
=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];
}
else//如果按过符号键
{b=b*10+table[num];
}
}else//如果按下的是'/'
{flag=1;fuhao=4;//4表示除号已按
}
i=table1[num];write_date(0x30+i);
}
P3=0xfd;if(P3!
=0xfd)
{delay(5);if(P3!
=0xfd)
{temp=P3&0xf0;switch(temp)
{case0xe0:
num=4;break;
case0xd0:
num=5;break;
case0xb0:
num=6;break;
case0x70:
num=7;
break;
}
}
while(P3!
=0xfd);
if(num==4||num==5||num==6&&num!
=7)//如果按下的是'4','5'或'6'
{if(j!
=0)
{write_com(0x01);j=0;
}if(flag==0)//没有按过符号键
{a=a*10+table[num];
}
else//如果按过符号键
{b=b*10+table[num];
}
}
else//如果按下的是'/'
{flag=1;fuhao=3;//3表示乘号已按
}
i=table1[num];write_date(0x30+i);
}
P3=0xfb;if(P3!
=0xfb)
{delay(5);
if(P3!
=0xfb)
{temp=P3&0xf0;switch(temp)
{case0xe0:
num=8;break;
case0xd0:
num=9;break;
case0xb0:
num=10; break;
case0x70:
num=11;break;
}
}
while(P3!
=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];
}
}
elseif(num==11)//如果按下的是'-'
{flag=1;fuhao=2;//2表示减号已按
}
i=table1[num];write_date(0x30+i);
}
P3=0xf7;if(P3!
=0xf7)
{ delay(5);if(P3!
=0xf7)
{temp=P3&0xf0;
switch(temp)
{case0xe0:
num=12;break;
case0xd0:
num=13;break;
case0xb0:
num=14;break;
case0x70:
num=15;break;
}
}
while(P3!
=0xf7);switch(num)
{case12:
{write_com(0x01);a=0;b=0;flag=0;fuhao=0;}//按下的是"清零"
break;case13:
{ //按下的是"0"
if(flag==0)//没有按过符号键
{a=a*10;write_date(0x30);P1=0;
}
elseif(flag==1)//如果按过符号键
{b=b*10;write_date(0x30);
}
}break;
case14:
{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;
}
elseif(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;
}
elseif(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;
}
elseif(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;
case15:
{write_date(0x30+table1[num]);flag=1;fuhao=1;}break;
}
}
}
main()
{init();while
(1)
{keyscan();
}
}
五.操作说明
用KeilC51对程序进行编译,当出现下图所示情况时,说明编译成功,然后将程序直接下进proteus设计图中的单片机内进行仿真,设计完成。
六.参考文献
【1】张毅刚.单片机原理及应用.高等教育出版社
【2】张毅刚.MCS-51单片机应用设计.哈张尔滨工业大学出版社
【3】王毅.单片机器件应用手册.人民邮电出版社