计算器课程设计报告.docx
《计算器课程设计报告.docx》由会员分享,可在线阅读,更多相关《计算器课程设计报告.docx(22页珍藏版)》请在冰点文库上搜索。
![计算器课程设计报告.docx](https://file1.bingdoc.com/fileroot1/2023-4/29/8b43c812-4716-45fe-a4a9-9e978d2365a9/8b43c812-4716-45fe-a4a9-9e978d2365a91.gif)
计算器课程设计报告
电子设计应用软件训练总结报告
学生姓名:
专业:
电子信息工程
班级:
学号:
指导教师:
训练时间:
2012年7月16日至2012年7月20日
一.任务说明
利用AT89C51单片机、8位共阳极蓝色数码管和计算器键盘构成一个计算器系统,可以实现加减乘除功能。
按照设计任务在Proteus6Professional中绘制电路原理图。
根据设计任务的要求编写程序,在Proteus下进行仿真,实现相应功能。
此次任务需要完成电路原理图的绘制、单片机C语言的编程。
目的是通过本次设计熟悉Proteus软件的工作环境,掌握基本的操作及流程以及对单片机汇编语言的进一步学习,使之前的学习得到巩固。
二.原理图绘制说明
要想实现其原理图的绘制,首先需要安装Proteus软件。
具体步骤如下:
1.打开此软件,进入Proteus界面,会出现查看样例设计对话框,点击取消键。
2.画图之前要新建一个图纸文件,在界面菜单栏中选择File—NewDesign选项,会出现多种图纸类型供选择,在本次课程设计中选择LandspaceA4纸张,鼠标左键点中图纸LandspaceA4类型,然后点击OK即可,操作如图1所示:
图1纸张选择
然后将文件保存到预先建立的文件夹中。
设计窗口便新建完毕,如图2所示:
图2新建的设计窗口
3.元件的查找及放置。
首先点击工具箱左上角的“P”按钮,如图3所示:
图3按钮“P”所在位置
弹出“PickDevices”操作界面,如图4所示:
图4“PickDevices”操作界面
在关键字窗口输入所需器件名称,如AT89C51,系统会自动搜索到此元件,如图5所示:
图5元件搜索界面
将所有元件搜索到以后按相应位置在图纸上放置好。
本实验所需的元器件如表1所示:
表1元件器件清单
元件
库
件数
51单片机
80C51
1
八位共阳极蓝数码管
7SEG-MPX8-CC-BULE
1
科学矩阵键盘
KEYPAD-SMALLCALC
1
4.布线及调整。
将鼠标移至所要连接器件的管脚处,鼠标箭头会变成红色虚线方框的样式,此时按住鼠标左键拖至将要连接的器件管脚处,松开左键即把两器件连接。
如果在连接器件时出现交叉或重叠,可以对连线或元件位置进行适当的调整。
布线后电路图如图6所示:
图6电路原理图
三.程序编译说明及流程图
1.MAIN程序说明
主程序中调用了三个子函数,分别是:
矩阵键盘扫描,数据显示函数,字符输入及转换。
程序流程图如下所示。
运算结果转换显示模块
加减乘除四则运算模块
字符输入及转换模块
符号判别子程序模块
单字符输入
子程序模块
主程序
图7主程序流程图
2.加减乘除四则运算模块程序说明
加减乘处四则运算子程序主要是用来识别输入运算符号,并将输入的第一个数和第二个数进行相应的运算。
程序流程图如下所示:
提示出错信息
进行加法运算
进行减法运算
进行乘法运算
进行除法运算
=‘+’?
=‘-’?
=‘*’?
=‘/’?
运算符比较
图8加减乘除四则运算程序流程图
2.运算结果转换显示模块程序说明
程序主要是用来转化输入输出的数据为BCD码,并通过八位数码管动态扫描显示。
程序流程图如下所示:
十六进制结果[DI]
余数
余数
余数
显示
>1000?
>100?
>10?
结果除10000
商减去30H
结果除1000
结果除100
结果除10
>10000?
图9运算结果转换显示程序流程图
3.矩阵键盘模块程序说明
N
程序主要是用来对4*4键盘进行扫描并且编码,该子程序的流程图如下所示:
图10矩阵键盘模块程序流程图
四.Proteus仿真说明
将此程序在Keil中进行编译生成“.hex”文件,将其导入单片机中,OK确定。
点击“开始”按键,进行仿真。
载入“.hex”文件如见图11所示:
图11载入“.hex”文件
导入程序后,开始仿真。
输入第一个数为3和第二个数4,显示结果如图12~13所示:
图12仿真结果数字3显示
图13仿真结果数字4显示
对输入的第一个数和第二个数相加,仿真结果如图14所示。
图14仿真结果数字7显示
对输入的第一个数和第二个数相减,仿真结果如图15所示。
图15仿真结果数字-1显示
对输入的第一个数和第二个数相乘,仿真结果如图16所示。
图16仿真结果数字12显示
对输入的第一个数和第二个数相除,仿真结果如图17所示。
图17仿真结果数字1显示
五.课程设计体会
在本次的Proteus应用软件训练中,主要是针对Proteus软件工作环境的熟悉以及掌握基本的操作,实现电路原理图的绘制及电路仿真的实现。
在这次的课程设计过程中,使我对Proteus的使用和仿真电路有了一定的了解和体会,对单片机的C语言编程和电路设计也有了新的认识,并且还锻炼了自己的思考能力和动手能力。
巩固了在单片机课中所学的知识,而且还学会了一些在书本以外的知识,丰富了我的单片机知识。
通过这次的课程设计,我充分认识到理论与实际相结合的重要性,理论知识再丰富,没有实际的操作经验,自身的能力是不会有所提高的。
参考文献
【1】杨将新,李华军,刘东骏等.单片机程序设计及应用从基础到实践.北京:
电子工业出版社,2006.
【2】张毅刚,刘杰.单片机原理及应用[M].哈尔滨:
哈尔滨工业大学出版社,2008.
【3】郭天祥.新概念51单片机C语言教程:
入门、提高、开发、拓展全攻略[M].北京:
电子工业出版社,2009.
【4】沈德全等.MCS-51系列单片机接口电路与应用程序实例.北京:
北京航空航天大学出版社,2004.
【5】李学礼.基于Proteus的8051单片机实例教程[M].北京:
电子工业出版社,2008.6.
【6】李勋,林广艳等.单片微型计算机大学读本.北京:
北京航空航天大学出版社,1998.11。
附录Ⅱ源程序代码
#include
#defineuintunsignedint
#defineucharunsignedchar
unsignedcharcodetable[]=
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x40
};
inti,r;
unsignedintz,key,flag,temp,symbol;
longintresult,first,second,sum;
ucharn,m,d,c,h,y,q,u;
inta[20],buff[20];
//***延时约250us***//
voiddlms(void)
{
uchari;
for(i=0;i<250;i++)
{}
}
//***键盘扫描延时函数***//
voiddelay1(uintm)
{
uintx,y;
for(x=m;x>0;x--)
for(y=110;y>0;y--);
}
//***LED动态扫描延时函数***//
voiddelay(z)
{
unsignedinty;
for(y=0;y}
//***运算并显示函数***//
voiddisplay()
{
if(n==11&m==1)//判断输入的数正负
{
symbol=1;
}
else
symbol=0;
if(n<=9)//判断输入是否为数值,并显示
{
flag++;
q=flag;
a[flag]=n;
}
if(n>9&n<15&n!
=14)//判断为运算符号,并清显示
{
c=1;
flag=0;
}
if(c==0)//将前后俩次输入的数值转化为十进制
{
first=a[7]*1000000+a[6]*100000+a[5]*10000+a[4]*1000+a[3]*100+a[2]*10+a[1]*1;
if(symbol==1)
{
first=first*(-1);
a[q+1]=16;//正数显示1
}
else
{first=first;
symbol=0;
//负数显示0
}
}
elseif(c==1)
{
second=a[7]*1000000+a[6]*100000+a[5]*10000+a[4]*1000+a[3]*100+a[2]*10+a[1]*1;
if(symbol==1)
{second=second*(-1);
a[q+1]=16;
}
else
{second=second;
symbol=0;
}
}
switch(n)//将运算符号值存入变量保存
{
case10:
h=1;//+
break;
case11:
h=2;//-
break;
case12:
h=3;//x
break;
case13:
h=4;//%
break;
case0:
h=0;//%
break;
default:
break;
}
if(flag==0)
m++;
if(n==15)//对数值进行加减乘除运算
{
switch(h)
{
case1:
result=first+second;//+
break;
case2:
result=first-second;//-
break;
case3:
result=first*second;//x
break;
case4:
result=first/second;//%
break;
case5:
result=0;//rest
break;
default:
break;
}
if(result<0)//对负数取绝对值,并显示正负
{
result=-result;
u=1;
}
else
{
a[8]=0;
}
a[7]=result/1000000;//将结果输出显示
a[6]=result%1000000/100000;
a[5]=result%100000/10000;
a[4]=result%10000/1000;
a[3]=result%1000/100;
a[2]=result%100/10;
a[1]=result%10;
for(i=1;i<=8;i++)
{if(a[i]>0)
buff[i]=1;
sum=sum+buff[i];
}
if(u==1)
{
a[sum+1]=16;
u=0;
}
y=1;
}
if(y==1&n==0)
{
//first=0;
//second=0;
flag=0;
y=0;
result=0;
symbol=0;
c=0;
h=0;
sum=0;
for(i=1;i<=8;i++)
{
a[i]=0;
buff[i]=0;
}
}
}
ucharkbscan(void)
{
ucharp,a;//无符号数
P3=0xf0;//高位置高,低位置低
if((P3&0xf0)!
=0xf0)//有按键则高位不全为
{
dlms();//延时以防干扰
if((P3&0xf0)!
=0xf0)//确实有按键
{
p=0xfe;//p=11111110从第1行开始扫描
while((p&0x10)!
=0)//当第位为时停止循环扫描,此时已扫描行
{
P3=p;//装入行扫描值
if((P3&0xf0)!
=0xf0)//如果此行有按键,接下去获取键值
{
a=P3;//P口值送置a
//键码对应的数值
if(a==0xde)n=8;//数值为8
if(a==0xed)n=4;//数值为4
if(a==0xdd)n=5;//数值为5
if(a==0xbd)n=6;//数值为6
if(a==0xeb)n=1;//数值为1
if(a==0xdb)n=2;//数值为2
if(a==0xbb)n=3;//数值为3
if(a==0xee)n=7;//数值为7
if(a==0xbe)n=9;//数值为9
if(a==0xe7)n=0;//正负号
if(a==0xd7)n=14;//数值为0
if(a==0xb7)n=15;//=
if(a==0x7e)n=13;//%
if(a==0x7d)n=12;//x
if(a==0x7b)n=11;//-
if(a==0x77)n=10;//+
while((P3&0xf0)!
=0xf0);//等待按键放开
display();//调用运算子函数
//return(n);//返回键值
}
else//不在第行,左移继续扫描
p=(p<<1)|0x01;//左移后低位为,所以将其置
}
}
}
return(16);//无按键返回初值
}
//***LED动态扫描函数***//
voidLED()
{for(i=0;i<=8;i++)//8个数码管循环点亮并显示
{if(r>0x80)
r=0x01;
else
r=r;
delay(40);
P2=r;
switch(r)
{
case0x01:
P1=~table[a[1]];
break;
case0x02:
P1=~table[a[2]];
break;
case0x04:
P1=~table[a[3]];
break;
case0x08:
P1=~table[a[4]];
break;
case0x10:
P1=~table[a[5]];
break;
case0x20:
P1=~table[a[6]];
break;
case0x40:
P1=~table[a[7]];
break;
case0x80:
P1=~table[a[8]];
break;
default:
break;
}
delay(40);
r=r<<1;
}
}
//***主函数***//
voidmain()
{
r=0x01;//LED移位变量赋值
while
(1)
{
kbscan();//调用键盘扫描和运算程序
LED();//调用LED显示程序
}
}
数