单片机简易计算器设计.docx
《单片机简易计算器设计.docx》由会员分享,可在线阅读,更多相关《单片机简易计算器设计.docx(34页珍藏版)》请在冰豆网上搜索。
单片机简易计算器设计
一、设计要求
1.设计4*4的键盘,其中10个数字键0~9,其余6个为“+”“-”“*”“/”“=”和“C”
2.设计2位LED接口电路
3.实现1位数的简单运算
二、硬件系统设计
1、LED接口电路
简易计算器需要2位8段码LED显示电路。
用8031单片机经8255A扩展2位8段码LED显示器,用8255A的A口作为段码(字形代码)数据口,PB0和PB1作为位控制端口。
在位控制口加集电极开路的反相高压驱动器74LS06以提供驱动LED显示器所需的足够大的电流,然后接至各数码显示器的共阴极端。
同理,在段码数据口集电极开路的正相高压驱动器74LS07提供足够大的电流,然后接到数码显示器的各段。
逻辑电路结构如下:
P2.7
ALE
P0.0~P0.7
74LS373
Q2~Q7
Q1
Q0
8031
P2.0~2.3
PSEN
A2~A7
A1
A0
2732
8~A11
OE
CE
XTAL2
XTAL1
WR
RD
RST
晶振6MHZ
CS
PA0
PA1
PA2
PA3
PA4
A1
PA5
A0
PA6
PA7
8255A
D0~D7
PB0
PB1
WRRD
RD
RESET
2X74LS06
2、键盘接口电路
简易计算器需要4*4的行列式键盘。
用8031单片机经8255A扩展4*4行列式键盘,8255A的B口和C口用于扩展键盘接口,B口高4位作为输出口,C口低4位作为输入口逻辑电路结构如下:
3、计算器逻辑电路图
将LED接口电路和键盘接口电路结合到一起就是简易计算器的逻辑电路图,如下:
8X74LS07
P2.7
ALE
P0.0~P0.7
CS
8031
P2.0~2.
PSEN
XTAL2
XTAL1
WR
RD
RST
G
74LS373
Q2~Q7
Q1
Q0
A2~A7
A1
A0
D0~D72732
A8~A11
OE
CE
A1
A0
PA0
PA1
PA2
PA3
PA4
PA5
PA6
PA7
8255A
D0~D7
PB0
PB1
PB4
PB5
PB6
PB7
WRPC0
RDPC1
RESETPC2
PC3
2X74LS06
4X4键盘
+5V
三、软件设计
1、LED显示程序设计
LED显示器由七段发光二极管组成,排列成
器排列形状如下图所示:
8字形状,因此也成为七段LED显示器,
为了显示数字或符号,要为LED显示器提供代码,即字形代码。
七段发光二极管,再加上一个小数点位,共计8段,因此提供的字形代码的长度正好是一个字节。
简易计算器用到的数字0~9的共阴极字形代码如下表:
0~9七段数码管共阴级字形代码
显示字型
g
f
e
d
c
b
a
段码
0
0
1
1
1
1
1
1
3fh
1
0
0
0
0
1
1
0
06h
2
1
0
1
1
0
1
1
5bh
3
1
0
0
1
1
1
1
4fh
4
1
1
0
0
1
1
0
66h
5
1
1
0
1
1
0
1
6dh
6
1
1
1
1
1
0
1
7dh
7
0
0
0
0
1
1
1
07h
8
1
1
1
1
1
1
1
7fh
9
1
1
0
1
1
1
1
6fh
2位LED显示的程序框图如下:
2、读键输入程序设计
为了实现键盘的数据输入功能和命令处理功能,每个键都有其处理子程序,为此每个键都对应一个码——键码。
为了得到被按键的键码,现使用行扫描法识别按键。
其程序框图如下:
3、主程序设计
1)数值送显示缓冲程序设计
简易计算器所显示的数值最大位两位。
要显示数值,先判断数值正负,如果是负值,则符号位显示“-”,然后将数值除以10,余数送显最最低位,判断商是否为0,若为0则返回,若不为0,则将商除以10,将余数送显高位。
程序框图如下:
(2)运算主程序设计
首先初始化参数,送LED低位显示“0”,高位不显示。
然后扫描键盘看是否有键输入,若有,读取键码。
判断键码是数字键、清零键还是功能键(“+”“-”“*”“/”“=”),是数值键则送LED显示并保存数值,是清零键则做清零处理,是功能键则又判断是“=”还是运算键,若是“=”则计算最后结果并送LED显示,若是运算键则保存相对运算程序的首地址。
运算主程序框图如下所示:
4、简易计算器源程序
OUTBITequ07FFDh;位控制口OUTSEGequ07FFCh;段控制口INequ07FFEh;键盘读入口
data1equ70h
data2equ71h
dizhi1equ72h
dizhi2equ73h
LEDBufequ60h;显示缓冲
ljmpStart
LEDMAP:
;八段管显示码db3fh,06h,5bh,4fh,66h,6dh,7dh,07hdb7fh,6fh,77h,7ch,39h,5eh,79h,71h
Delay:
;延时子程序movr7,#0
DelayLoop:
djnzr7,DelayLoop
djnzr6,DelayLoopret
DisplayLED:
movr0,#LEDBufmovr1,#2;
movr2,#00000010b
Loop:
movdptr,#OUTBIT
mova,#0
movx@dptr,a;
共2个八段管从左边开始显示
关所有八段管
mova,@r0
movdptr,#OUTSEGmovx@dptr,a
movdptr,#OUTBIT
mova,r2
movx@dptr,a;
显示一位八段管
movr6,#1callDelay
mova,r2rra
movr2,a
显示下一位
incr0
djnzr1,Loop
ret
TestKey:
movdptr,#OUTBITmova,#0
输出线置为0
读入键状态
高四位不用
键码定义
找出键所在列
下一列
该列有键入
没有键按下,返回0ffh
键值=列X4+行
movx@dptr,a;movdptr,#INmovxa,@dptr;cplaanla,#0fh;
ret
KeyTable:
;
db0dh,0ch,0bh,0ahdb0eh,03h,06h,09hdb0fh,02h,05h,08hdb00h,01h,04h,07h
GetKey:
movdptr,#OUTBITmovP2,dphmovr0,#Low(IN)movr1,#00100000bmovr2,#4
KLoop:
mova,r1;
cpla
movx@dptr,a
cpla
rra
movr1,a;
movxa,@r0
cpla
anla,#0fhjnzGoon1;
djnzr2,KLoop
movr2,#0ffh;sjmpExit
Goon1:
movr1,a;
mova,r2
deca
rla
rla
movr2,a
;r2=(r2-1)*4
mov
a,r1
;r1
中为读入的行值
mov
r1,#4
LoopC:
rrc
a;
移位找出所在行
jc
Exit
inc
r2;
r2=r2+
行值
djnz
r1,LoopC
Exit:
mov
a,r2;
取出键码
mov
dptr,#KeyTable
movc
a,@a+dptr
mov
r2,a
等键释放
WaitRelease:
movdptr,#OUTBIT;clramovx@dptr,a
movr6,#10callDelaycallTestKeyjnzWaitRelease
mova,r2
ret
Start:
mov
sp,#40h
mov
LEDBuf+0,#0
mov
LEDBuf+1,#03fh
mov
dptr,#7FFFh
mov
a,#89h
movx
@dptr,a
MLoop:
call
DisplayLED;
显示
call
TestKey;
有键入?
jz
MLoop;
无键入,继续显示
call
GetKey;
读入键码
Jisuan:
movr3,acjner3,#0fh,Qita
判断是否为清零键?
mov
r3,#00h;
mov
r4,#00h
mov
r5,#00h
mov
data1,#00h
mov
data2,#00h
mov
dizhi1,#00h
mov
dizhi2,#00h
mov
LEDBuf+0,#0
mov
LEDBuf+1,#03fh
ljmp
MLoop
Qita:
clr
c
cjne
r3,#0ah,follow;
follow:
清零
判断是数字键还是功能键?
jcShuziljmpGn
mov
a,r3
mov
data1,a
ljmp
Xs;
显示第一次输入的数值
Shuzi2:
mov
a,r3
mov
data2,a
ljmp
Xs;
显示第二次输入的数值
Gn:
movr4,#01h;
将01h给r4,说明已有运算符输入
cjne
r3,#0eh,Ja;
判断键值是否为“=”?
mov
r4,#00h;
将r4清零
mov
a,dizhi1;
执行“=”
mov
dph,a
mov
a,dizhi2
mov
dpl,a
mov
a,#00h
jmp
@a+dptr;
转到本次输入的算法程序
Ja:
cjne
r3,#0ah,Jn;
若键值为“+”则将“+”的程序首地址存在
movdptr,#Jia
dizhi1和dizhi2中
mov
a,dph
mov
dizhi1,a
mov
a,dpl
mov
dizhi2,a
ljmp
MLoop
data1
判断是否已有运算符输入,没有就将数值存在
,有就将数值存在data2
Shuzi:
mova,r4jnzShuzi2
Jn:
cjner3,#0bh,Cemovdptr,#Jian
mov
a,dph
mov
dizhi1,a
mov
a,dpl
mov
dizhi2,a
ljmp
MLoop
若键值为“-”则将“-”的程序首地址存dizhi1和dizhi2中
Ce:
cjner3,#0ch,Cu;movdptr,#Cheng
若键值为“*”则将“*”的程序首地址存在dizhi1和dizhi2中
mov
a,dph
mov
dizhi1,a
mov
a,dpl
mov
dizhi2,a
ljmp
MLoop
Cu:
cjner3,#0dh,Zhuan;
若键值为“/”则将“/”的程序首地址存在
movdptr,#chudizhi1
和dizhi2中
mova,dph
movdizhi1,a
mova,dpl
movdizhi2,a
Zhuan:
ljmpMLoop
Jia:
mova,data1;加法程序adda,data2
ljmpXs
Jian:
mova,data1;减法程序subba,data2
ljmpXs
Cheng:
mova,data1;乘法程序movb,data2
mulab
ljmpXs
Chu:
mova,data1;除法程序movb,data2
显示个位数字
divab
Xs:
movb,#10divabmovr5,amova,b
movdptr,#LEDMapmovca,@a+dptrmovLEDBuf+1,amova,r5
First:
运算完后继续扫描键盘
显示十位数字
cjnea,#0,Next
ljmpMLoop;
Next:
movb,#10;divab
movr5,a
mova,b
movdptr,#LEDMapmovca,@a+dptrmovLEDBuf+0,amova,r5ljmpFirst
end
四、系统调试与存在的问题
1.在打开一个程序要进行编译运行时,要在项目中打开它,而不是单单以一个文件的形式打开。
2.打开WAVE6000后,需要对仿真器进行设置,然后才能用其对所编程序进行编译并执行。
3.试验箱上提供的6位的LED显示器和4*6的键盘,而简易计算器只用两位LED显示器和4*4键盘,所以必须用软件方法把前4位LED和键盘后2列屏蔽掉。
4.十位上的LED显示管有数字时才显示,没有数字时不显示,而不是显示“0”,做清零操作后LED显示器个位显示“0”,而全部关闭不显示。
五、心得体会
课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。
随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说得是无处不在。
因此作为电子信息工程专业的学生来说掌握单片机的开发技术是十分重要的。
我的题目是简易计算器,对于我们这些实践中的新手来说,这是一次考验。
怎么才能找到课堂所学与实际应用的最佳结合点?
怎样让自己的业余更接近专业?
怎样让自己的计划更具有序性,而不会忙无一用?
这都是我们所要考虑和努力的。
这次课程设计我学到很多很多的东西,学会了怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。
不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识,掌握了一种系统的研究方法,可以进行一些简单的编程。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不够好。
这次课程设计通过我们小组的努力终于顺利完成了,在设计中遇到了很多编程问题,最后在老师的辛勤指导下,终于迎刃而解,在此我表示感谢!
同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!
参考文献
#include
signedlongA1,B1,RESULT;
charC=0,F=0,STATE=0,ANSWER=0,KEY=0;//定义标志位,F=0存第一个数,F=1存第二个数,C标志显示初值与否
charxuhao1=0,xuhao2=0;xuhao3=0;
charSHU1[8]={0},SHU2[8]={0},SHU3[8],CHUZHI[1]={0};
charcodebiao[4][4]={{1,4,7,0},{2,5,8,'R'},{3,6,9,'='},{'+','-','*','/'}};
charcodeDUANMA[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//
voidDELAY(chart)
{
inta=0;
for(t;t>=0;t--)
for(a;a<=100;a++);
}
//
CLEAR()
{
chari=0;
A1=0;B1=0;RESULT=0;xuhao1=0;xuhao2=0;xuhao3=0;
F=0;C=0;STATE=0;ANSWER=0;KEY=0;for(i;i<8;i++)
SHU1[i]=0;
SHU2[i]=0;
SHU3[i]=0;
}
}
//
charSAOMIAO()
{
P1=0x0f;
if(P1!
=0x0f)
{
DELAY
(1);
if(P1!
=0x0f)return
(1);elsereturn(0);
}
return(0);
}
//
signedlongZHUANHUAN(charH[8],charX){
chari;signedlongM=0;
X=X-1;
for(i=0;i<=X;i++)
{
M=M*10+H[i];
}
return(M);
}
//
voidFANZHUANHUAN(signedlongM)
N=M;
M=(M/10);
SHU3[xuhao3]=(char)N;xuhao3=xuhao3+1;
}
b=xuhao3-1;
//if(xuhao3>=8);
for(i=0;i<=b/2;i++)//为满足DISPLA(Y)函数调用的条件,SHU3中的数要按SHU1,SHU2中的
{//存储方式存储,即,最高位数字存入第一个数组单元中
a=SHU3[i];
SHU3[i]=SHU3[b-i];
SHU3[b-i]=a;
}}
//signedlongJIA(signedlongX,signedlongY){
signedlongresult;
result=X+Y;
return(result);
}
//
signedlongJIAN(signedlongX,signedlongY){
signedlongresult;result=X-Y;
return(result);
}
//
signedlongCHENG(signedlongX,signedlongY){
signedlongresult;
result=X*Y;return(result);
}
//
signedlongCHU(signedlongX,signedlongY){
signedlongresult;result=X/Y;
return(result);}
//
voidinter0(void)interrupt0using0
{
charhang,lie;switch(P1)
{
case0x0e:
lie=0;break;
case0x0d:
lie=1;break;
case0x0b:
lie=2;break;
case0x07:
lie=3;break;
//查表获得按下的键值,按键标志位置1
//按下的是数字键则进行相应存储
//若没有运算符按下,键值存入SHU1中
{
SHU1[xuhao1]=KEY;
xuhao1=xuhao1+1;
SHU2[xuhao2]=KEY;
//若有运算符按下,键值存入SHU2中
case0xe0:
hang=0;break;case0xd0:
hang=1;break;
case0xb0:
hang=2;break;
case0x70:
hang=3;break;
}
KEY=biao[hang][lie];C=1;
if(KEY>=0&&KEY<=9)
xuhao2=xuhao2+1;
}
}
elseif((KEY=='+')||(KEY=='-')||(KEY=='*')||(KEY=='/')||(KEY=='=')||(KEY=='R'))
{
F=1;//有运算符按下,运算标志位置1if(KEY=='+'){STATE=1;C=0;}
elseif(KEY=='-'){STATE=2;C=0;}//判断运算符,且相应标识位赋值
elseif(KEY=='*'){STATE=3;C=0;}
elseif(KEY=='/'){STATE=4;C=0;}
elseif(KEY=='R')CLEAR();//复位键按下,调用复位函数,所有标志位,存储数组
清零
elseif(KEY=='=')ANSWER=1;
}
//
voidDISPLAY(charSHU[8],charxuhao)
chari;charj;
chara=0xfe;i=xuhao-1;
if(i<8)
for(i;i>=0;i--)//动态显示缓冲单元中的数
}
}
for(i;i>0;i--)
P0=0xff;
{
IT0=1;
//外部中断0初始化
EX0=1;
//中断采用跳沿触发方式
//主函数
EA=1;
while
(1)
//是否是有键按下,没有则显示0
//假如按下的是等号,则进行相应计算,否则显示按的数字
//计算结果反转换存入SHU3中
//计算结果反转换存入SHU3中
P2=a;j=SHU[i];P0=DUANMA[j];DELAY(3);a=(a<<1)+1;
seif(STATE==3)
RESULT=CHENG(A1,B1)
FANZHUANHUAN(RESULT);
//计算结果反转换存入SHU3中
}
elseif(STATE==4)
{
RE