简易计算器.docx
- 文档编号:10329315
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:23
- 大小:71.12KB
简易计算器.docx
《简易计算器.docx》由会员分享,可在线阅读,更多相关《简易计算器.docx(23页珍藏版)》请在冰豆网上搜索。
简易计算器
简易加减器的设计
摘要:
近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。
在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。
本任务是个简易的两位数的四则运算,程序都是根据教材内和网络中的程序参考编写而成,在功能上还并不完善,限制也较多。
本任务重在设计构思与团队合作,使得我们用专业知识、专业技能分析和解决问题全面系统的锻炼。
关键词:
单片机计算器范围加减乘除
1引言
1.1计算器的历史
说起计算器,值得我们骄傲的是,最早的计算工具诞生在中国。
中国古代最早采用的一种计算工具叫筹策,又被叫做算筹。
这种算筹多用竹子制成,也有用木头,兽骨充当材料的。
约二百七十枚一束,放在布袋里可随身携带。
直到今天仍在使用的珠算盘,是中国古代计算工具领域中的另一项发明,明代时的珠算盘已经与现代的珠算盘几乎相同。
17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的"纳皮尔算筹",英国牧师奥却德发明了圆柱型对数计算尺,这种计算尺不仅能做加减乘除、乘方、开方运算,甚至可以计算三角函数,指数函数和对数函数,这些计算工具不仅带动了计算器的发展,也为现代计算器发展奠定了良好的基础,成为现代社会应用广泛的计算工具。
1.2电子计算器的特殊键
在使用电子计算器进行四则运算的时候,一般要用到数字键,四则运算键和清除数据键。
除了这些按键,还有一些特殊键,可以使计算更加简便迅速。
2单片机概述
单片机微型计算机是微型计算机的一个重要分支,也是颇具生命力的机种。
单片机微型计算机简称单片机,特别适用于控制领域,故又称为微控制器。
通常,单片机由单块集成电路芯片构成,内部包含有计算机的基本功能部件:
中央处理器、存储器和I/O接口电路等。
因此,单片机只需要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。
单片机经过1、2、3、3代的发展,目前单片机正朝着高性能和多品种方向发展,它们的CPU功能在增强,内部资源在增多,引角的多功能化,以及低电压底功耗。
3芯片简介
3.1MSC-51芯片简介
MCS-51单片机内部结构
8051是MCS-51系列单片机的典型产品,我们以这一代表性的机型进行系统的讲解。
8051单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明:
·中央处理器:
中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。
·数据存储器(RAM)
8051内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。
图1
·程序存储器(ROM):
8051共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。
·定时/计数器(ROM):
8051有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。
·并行输入输出(I/O)口:
8051共有4组8位I/O口(P0、P1、P2或P3),用于对外部数据的传输。
·全双工串行口:
8051内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。
·中断系统:
8051具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。
·时钟电路:
8051内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但8051单片机需外置振荡电容。
引脚图如下:
4相关知识
4.1数码管显示
在本任务中用8段数码管显示当前数值的百,十,个,由于数码管个数多,如采用静态显示方式,则占用单片机的I/O口线太多,如果用定时器/计数器的串行移位寄存器工作方式及外接串入并出移位寄存器74LS164的方式,则电路复杂。
所以,在数码管个数较多时,常采用动态显示方式。
如图1-1所示为单片机应用系统中的一种数码管动态显示电路图,数码管的相同段并联在一起,由一个8位I/O(P1口)输出字形码控制显示某一字形,每个数码管的公共端由另外一个I/O口(P0口)输出的字位码控制,即数码管显示的字形是由单片机I/O口输出的字形码确定,而哪个数码管点亮是由单片机I/O口输出的字位码确定的。
4个数码管分时轮流循环点亮,在同一时刻只有1个数码管点亮,但由于数码管具有余辉特性及人眼具有视觉暂留特性,所以适当地选取循环扫描频率,看上去所有数码管是同时点亮的,察觉不出闪烁现象。
动态显示方式所接数码管不能太多,否则会因每个数码管所分配的实际导通时间太少,使得数码管的亮度不足。
在本任务中,为了简便,字形码和字位码都没由加驱动电路,在实际应用中应加驱动电路。
数码管有共阴极和共阳极两种,对于共阳数码管,字形驱动输出0有效,字位驱动输出1有效;而对于共阴数码管则相反,即:
字形驱动输出1有效,字位驱动输出0有效。
4.2矩阵按键
键盘是单片机系统中最常用的人机对话输入设备,用户通过键盘向单片机输入数据或指令。
键盘控制程序需完成的任务有:
监测是否有键按下,有键按下时,在无硬件去抖的动电路时,应用软件延时方法消除按键抖动影响;当有多个键同时按下时,只处理一个按键,不管一次按键持续多长时间,仅执行一次按键功能程序。
矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,思路:
先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。
但是,在程序的写法上,采用了最简单的方法,使得程序效率最高。
本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。
本键盘扫描程序的优点在于:
不用专门的按键延时程序,提高了CPU效率,也不用中断来扫描键盘,节省了硬件资源。
另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。
本键盘扫描子程序名叫key,每次要扫描时用lcallkey调用即可。
开始
5流程图
延时
键盘扫描
初始化端口
否
是
否
是否有按键按下
两次结果是否相同
是
检测键值是否>9
否
P指针是否>0x310
是
存储到单元
指针+1
存储数据
结束
键盘扫描流程图
是
调用加子程序
是否为+
键值判断
是
否
是否为—
调用减子程序
否
是
是否为*
调用乘子程序
是
否
是否为%
调用除子程序
结果存入result变量
运算操作流程
否
Result结果是否大于10
是
求余送端口
整除10取商送端口
显示
LED显示流程
6源程序及说明
#include
//#include
#defineLEDS8
/***按键程序***/
charkeyscan();
/***显示程序***/
voiddisplay();
chardsp[9]={0,0,12,12,12,12,12,12,12};//初始化显示数组
/***计算程序***/
voidcalculate(chark,charc1[8],charc2[8]);
/***片选***/
unsignedcharcodeSelect[]=
{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
/***码选***/
unsignedcharcodeLED_CODES[]=
{0xC0,0xF9,0xA4,0xB0,0x99,//0-4
0x92,0x82,0xF8,0x80,0x90,//5-9
0x86,0xAF,0xFF,0x7F,0xBF,};//E,r,空格,.,-
/***main函数***/
voidmain(void)
{
chari,j,k,c;
chara[8],b[8];
/***定时1ms***/
TMOD=0;
TL0=-(1000/256);
TH0=-(1000%256);
EA=1;//总中断开关
ET0=1;//开中断
TR0=1;//启用计数器0
KSC:
do
{
for(i=1;i<9;i++)//数字录入循环
{
dsp[0]=keyscan();
if(c==2&&dsp[0]<10)//此段代码验证是否有旧的计算结果在显示,且不再参与新计算
{
dsp[1]=dsp[0];
for(j=2;j<9;j++)
dsp[j]=12;
c=0;
}
elseif(c==2&&dsp[0]>9)//旧的计算结果将参与新的计算,作为第一个数
{
c=0;
}
if(dsp[0]==0&&dsp[1]==0&&dsp[2]==12)//个位为0且十位为空时按下0,按键无效,跳回KSC等待正确输入
{
/***goto跳转标志***/
gotoKSC;
}
elseif(dsp[0]>9)break;//有操作符按下,跳出数字录入循环
else
{for(j=i;j>0;j--)
dsp[j]=dsp[j-1];//移位,以正确显示数字
}
}
if(i==9)//判断是否输入8个有效数字,是则等待操作符,否则直接判断操作符
{
do//使用dowhile无论是否第一个数都取一次操作符
{
dsp[0]=keyscan();//获取操作符号
if(dsp[0]==14||dsp[0]<10)//按下C或者第9位数字清零
{
dsp[1]=0;
for(i=2;i<9;i++)
dsp[i]=12;
c=0;
}
}while((dsp[0]==15)&&(c==0));//等号被按下,等待新的操作符(仅对第一个数字有效)
}
elseif(dsp[0]==14)//按下C清零
{
dsp[1]=0;
for(i=2;i<9;i++)
dsp[i]=12;
c=0;
}
while(dsp[0]==15&&c==0)//未输满8位且是第一个数字即按下等号,等待非等号操作符
{
dsp[0]=keyscan();//获取操作符号
if(dsp[0]==14||dsp[0]<10)//按下C或者数字都进行清零,重新输入a
{
dsp[0]=14;//将dsp[0]置为14,防止因数字清零未能拦截
dsp[1]=0;
for(i=2;i<9;i++)
dsp[i]=12;
c=0;
}
}
}while(dsp[0]==14);//数字输入未完成即按下C,重新等待输入
do
{
if(c==0)//没有数字输入
{
k=dsp[0];//存计算符(循环内已排除C、=、数字)
for(i=0;i<8;i++)//将第一个数存入a[8]
{
a[i]=dsp[i+1];
}
dsp[1]=0;//清零
for(i=2;i<9;i++)
dsp[i]=12;
c=1;//已输入a
/***goto跳转标志***/
gotoKSC;
}
elseif(c==1)
{
for(i=0;i<8;i++)//将第二个数存入b[8]
{
b[i]=dsp[i+1];
}
c=2;//已输入b
if(dsp[0]!
=15)//b输完后操作符不是等号
{
calculate(k,a,b);
for(i=0;i<8;i++)//将计算结果存入a[8],a值更新
{
a[i]=dsp[i+1];
}
k=dsp[0];//更新计算符
c=1;
/***goto跳转标志***/
gotoKSC;
}
}
}while((dsp[0]==15)&&(c<2));//直到ab输入完成且按下等号
calculate(k,a,b);//进行最后计算
/***goto跳转标志***/
gotoKSC;//跳回KSC,等待新一轮计算
while
(1);//防止程序跑飞
}
charkeyscan()
{
charKeyL;
charKeyR;
charj;
do
{
do
{
P3=0xF0;
P3=P3|0xF0;//行扫描11110000
if(P3!
=0xF0)
{
KeyL=P3;
P3=0x0F;
P3=P3|0x0F;//列扫描00001111
KeyR=P3;
}
}while(KeyL==0xF0||KeyR==0x0F);
for(j=0;j<12;j++)//延时0.001s=1ms
{;}
}while(P3!
=0x0F);
switch(KeyL&KeyR)
{
case0x28:
{return0;break;}
case0x11:
{return1;break;}
case0x21:
{return2;break;}
case0x41:
{return3;break;}
case0x12:
{return4;break;}
case0x22:
{return5;break;}
case0x42:
{return6;break;}
case0x14:
{return7;break;}
case0x24:
{return8;break;}
case0x44:
{return9;break;}
case0x81:
{return10;break;}//加法(第一行,第四列)
case0x82:
{return11;break;}//减法(第二行,第四列)
case0x84:
{return12;break;}//乘法(第三行,第四列)
case0x88:
{return13;break;}//除法(第四行,第四列)
case0x18:
{return14;break;}//清零(第四行,第一列)
case0x48:
{return15;break;}//计算结果(第四行,第三列)
}
}
voiddisplay()interrupt1using1//利用定时器中断实现间时显示
{
chari,j,h;
ET0=0;
for(j=8;j>0;j--)//扫描8次
{
for(i=7;i>=0;i--)//从高位到低位扫描显示
{
P2=0;
P1=LED_CODES[dsp[8-i]];
P2=Select[i];
for(h=0;h<8;h++)
{;}
}
}
TL0=-(1000/256);
TH0=-(1000%256);
ET0=1;
}
voidcalculate(chark,chara[8],charb[8])
{
charr[8];
longi,x,y;
i=0;
x=0;
y=0;
for(i=7;i>0;i--)//数值转化,将代表空格的12转化为数字0,因为个位不显示空格,默认为0,所以不转化
{
while(a[i]==12)a[i]=0;
while(b[i]==12)b[i]=0;
}
x=a[4];
x=10000*x;
x=x+a[0]+a[1]*10+a[2]*100+a[3]*1000+a[5]*100000+a[6]*1000000+a[7]*10000000;
y=b[4];
y=10000*y;
y=y+b[0]+b[1]*10+b[2]*100+b[3]*1000+b[5]*100000+b[6]*1000000+b[7]*10000000;
if(k==10)//加法运算
{
x=x+y;
if(x>99999999)//大于8位,显示“Err”
{
r[0]=11;//r
r[1]=11;//r
r[2]=10;//E
r[3]=12;//空格
r[4]=12;
r[5]=12;
r[6]=12;
r[7]=12;
}
else
{
r[0]=x%10;
r[1]=(x%100)/10;
r[2]=(x%1000)/100;
r[3]=(x%10000)/1000;
r[4]=(x%100000)/10000;
r[5]=(x%1000000)/100000;
r[6]=(x%10000000)/1000000;
r[7]=x/10000000;
}
}
if(k==11)//减法运算
{
if(x { x=y-x; if(x>9999999) { r[0]=11;//r r[1]=11;//r r[2]=10;//E r[3]=12;//空格 r[4]=12; r[5]=12; r[6]=12; r[7]=12; } else { r[0]=x%10; r[1]=(x%100)/10; r[2]=(x%1000)/100; r[3]=(x%10000)/1000; r[4]=(x%100000)/10000; r[5]=(x%1000000)/100000; r[6]=(x%10000000)/1000000; r[7]=x/10000000; for(i=7;i>0;i--)//将有效数字的高一位转化为-号 { if(r[i]==0&&r[i-1]! =0) { r[i]=14; break; } } } } else { x=x-y; r[0]=x%10; r[1]=(x%100)/10; r[2]=(x%1000)/100; r[3]=(x%10000)/1000; r[4]=(x%100000)/10000; r[5]=(x%1000000)/100000; r[6]=(x%10000000)/1000000; r[7]=x/10000000; } } if(k==12)//乘法运算 { i=x; x=x*y; if(y==0) { x=0; } elseif(x>99999999||x { r[0]=11;//r r[1]=11;//r r[2]=10;//E r[3]=12;//空格 r[4]=12; r[5]=12; r[6]=12; r[7]=12; } else { r[0]=x%10; r[1]=(x%100)/10; r[2]=(x%1000)/100; r[3]=(x%10000)/1000; r[4]=(x%100000)/10000; r[5]=(x%1000000)/100000; r[6]=(x%10000000)/1000000; r[7]=x/10000000; } } if(k==13)//除法运算 { if(y==0)//被除数不能为0 { r[0]=11;//r r[1]=11;//r r[2]=10;//E r[3]=12;//空格 r[4]=12; r[5]=12; r[6]=12; r[7]=12; } else { x=x/y; r[0]=x%10; r[1]=(x%100)/10; r[2]=(x%1000)/100; r[3]=(x%10000)/1000; r[4]=(x%100000)/10000; r[5]=(x%1000000)/100000; r[6]=(x%10000000)/1000000; r[7]=x/10000000; } } for(i=7;i>0;i--)//数值转化,将高位的无效数字0转化为空格符12 { if(r[i]==0) r[i]=12; else break; } for(i=0;i<8;i++)//将计算结果存入dsp[9],显示数更新 { dsp[i+1]=r[i]; } } 7结论与心得 本系统就是充分利用了8051芯片的I/O引脚。 系统统采用MSC-51系列单片机Intel8051为中心器件来设计计算器控制器,实现了能根据实际输入值显示并存储,计算程序则是参照教材。 至于位数和功能,如果有需要可以设计扩充原系统来实现。 通过这次毕业设计,使我们得到了一次用专业知识、专业技能分析和解决问题全面系统的锻炼。 使我们在单片机的基本原理、单片机应用系统开发过程,以及在常用编程设计思路技巧(特别是汇编语言)的掌握方面都能向前迈了一大步,为日后成为合格的应用型人才打下良好的基础。 参考文献 1单片机应用技术(汇编语言),中国劳动社会保障出版社,2006.6 2网络文章: 3单片机开发与实践,机械工业出版社 电信郑飞唐俊
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简易 计算器