51单片机计算器程序设计报告.docx
《51单片机计算器程序设计报告.docx》由会员分享,可在线阅读,更多相关《51单片机计算器程序设计报告.docx(12页珍藏版)》请在冰豆网上搜索。
51单片机计算器程序设计报告
长沙民政职业技术学院
课程设计报告
课题名称:
51单片机的计算器设计
课程:
单片机技术及应用
专业:
应用电子技术
学生姓名
周扬
孔计
张娇
陈实
学号
17
15
14
19
班级
0733
0733
0733
0733
指导老师
方跃春老师
应用电子技术教研室
2009年9月2日
一、课题任务及要求
要求:
1、掌握数码管移位动态扫描显示的编程方法
2、掌握矩阵扫描的编程方法
3、掌握数据在内部运算的编程方法
任务:
1、实现最大6位正整数加、减、乘、除
2、具备清零、等于功能
3、16个按键功能依次为:
数字0、数字1、数字2、数字3、数字4、数字5、数字6、数字7、数字8、数字9、清零、等于、加、减、乘、除
二、硬件设计
1.原理图
2.原理分析
该设计通过89C51芯片控制6个一位数码管显示,并实时检测按键按下情况来实现计算器功能,16个按键有10个为数字按键其他6个分别为加、减、乘、除、复位、等于
电路接上电源后数码管显示个位显示数字0,芯片对按键进行实时扫描,通过矩阵键盘进行计算,特别注意的是,当结果为负数时,数码管显现EORR。
(一)、硬件部分
1、数码管为一位共阴数码管,共6个;故在段码输出口外加NPN型三极管作驱动
2、51芯片P1口接键盘端(矩阵按键)、P3口接段码、P2口的P2_0—P2_5接位码
3、按键为四乘四矩阵,共16个键
(二)、软件部分
1、数码管移位显示的实现是通过标志位wei2的数值变化控制dispiay函数显示位来实现的
2、程序的重要算法是通过类型为unsignedint的数temp和数组str[]实现整体加减乘除、各位显示的只要弄懂这一算法,此程序就可轻易掌握
3.PCB图
略。
4.元件清单及造价预算
按键20个单价0.2元总计4元
万用板2块单价4元总计8元
一位共阴数码管6个单价2元总计2元
三极管7个单价0.2元总计1.4元
1K电阻20个单价0.01元总计2毛
排插及排线5对单价1元总计5元
电容3个单价0.2元总计6毛
晶振1个单价1元总计1元
8051芯片1个单价6元总计6元
费用总计26.2元
5.实物照片
三、程序设计
头程序
str[6]=str[5]=str[4]=str[3]=str[2]=str[1]=10;
str1[6]=str1[5]=str1[4]=str1[3]=str1[2]=str#include//51单片机基本定义头文件
#include//循环位移头文件
#defineucharunsignedchar//宏定义
#defineuintunsignedint
sbitP1_4=P1^4;//IO端口定义(矩阵扫描后4位端口)
sbitP1_5=P1^5;
sbitP1_6=P1^6;
sbitP1_7=P1^7;
uchari,num,s;//全局变量定义
ucharwei,wei2,ss,ss1,ss2,str1[]={0,0,0,0,0,0,0};
longtemp,temp1,str[]={10,10,10,10,10,10,10};
ucharcodedutable[]={//段位编码
0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
ucharcodewetable[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
voidinit();//函数声明
voidpanduan();
voiddisplay();
voiddelay(uintz);
voidshaomiao();
voidmain()//主函数
{
init();//调用变量初始化函数
while
(1)//大循环
{
shaomiao();//调用矩阵扫描加处理函数
display();//调用显示函数
}
}
voidinit()//变量初始化函数
{
ss2=0;
wei2=1;
temp1=0;
ss=0;
ss1=0;
temp=0;
wei=0;
num=0;
}
voiddelay(uintz)//延时函数(单位ms)
{
uchari;
uintj;
for(j=z;j>0;j--)
for(i=114;i>0;i--);
}
voidshaomiao()//扫描加处理函数
{
for(i=0,s=0xfe;i<4;i++)//低四位端口依次赋值1
{
P1=s;//对P1口赋值
panduan();//调用判断处理函数
s=_crol_(s,1);//s循环位左移
s=s|0xf0;//进行位或运算
}(使高4位复原)
}
voidpanduan()
{
ucharn;
if(P1_4==0||P1_5==0||P1_6==0||P1_7==0)
{
delay(10);
P1=s|0xf0;
if(P1_4==0||P1_5==0||P1_6==0||P1_7==0)
{
if(P1_4==0)
{n=1;num=i*4+n-1;}
elseif(P1_5==0)
{n=2;num=i*4+n-1;}
elseif(P1_6==0)
{n=3;num=i*4+n-1;}
elseif(P1_7==0)
{n=4;num=i*4+n-1;}
if(num<10&&wei!
=7)
{
wei++;
if(ss1==1)
{
temp=0;
str[6]=str[5]=str[4]=str[3]=str[2]=str[1]=10;str1[6]=str1[5]=str1[4]=str1[3]=str1[2]=str1[1]=0;
ss1=0;
}
str[wei]=num;
if(str[1]!
=10)temp=str[1];
if(str[2]!
=10)temp=str[1]*10+str[2];
if(str[3]!
=10)temp=str[1]*100+str[2]*10+str[3];
if(str[4]!
=10)temp=str[1]*1000+str[2]*100+str[3]*10+str[4];
if(str[5]!
=10)temp=str[1]*10000+str[2]*1000+str[3]*100+str[4]*10+str[5];
if(str[6]!
=10)temp=str[1]*100000+str[2]*10000+str[3]*1000+str[4]*100+str[5]*10+str[6];
}
if(num>=10)
{
wei=0;
if(num==10)
{
temp=0;
1[1]=0;
wei=0;
temp1=0;
ss=0;
wei2=1;
}
if(ss1==0&&num==11||(ss1==0&&ss2!
=0&&num>11&&num<16))
{
if(num==11)
ss2=0;
switch(ss)
{
case0:
break;
case1:
temp=temp+temp1;break;
case2:
temp=temp1-temp;break;
case3:
temp=temp*temp1;break;
case4:
temp=temp1/temp;break;
}
if(temp>999999)
temp=0;
ss1=1;
}
if(num==12)
{
temp1=temp;
ss=1;ss1=1;ss2=1;
}
if(num==13)
{
temp1=temp;
ss=2;ss1=1;ss2=1;
}
if(num==14)
{
temp1=temp;
ss=3;ss1=1;ss2=1;
}
if(num==15)
{
temp1=temp;
ss=4;ss1=1;ss2=1;
}
}
}
str1[6]=temp/100000;
str1[5]=temp%100000/10000;
str1[4]=temp%10000/1000;
str1[3]=temp%1000/100;
str1[2]=temp%100/10;
str1[1]=temp%10/1;
if(str1[1]!
=0)
wei2=1;
if(str1[2]!
=0)
wei2=2;
if(str1[3]!
=0)
wei2=3;
if(str1[4]!
=0)
wei2=4;
if(str1[5]!
=0)
wei2=5;
if(str1[6]!
=0)
wei2=6;
}
while(P1_4==0||P1_5==0||P1_6==0||P1_7==0);
}
voiddisplay()
{
chari1;
for(i1=1;i1{
if(num==0&&ss==4||temp<0)
{
P2=wetable[0];
P3=dutable[14];
}
else
{
P2=wetable[i1-1];
P3=dutable[str1[i1]];
delay(10);
P3=0xff;
}
}
}
四、调试结果
1、硬件调试
a.把电路板焊好后,先通过检查电路板表面检查是否有漏焊、错焊、接触不良等
b.编写检测程序逐个点亮数码管,检查数码显示部分是否有硬件问题
c.编写检测程序检测矩阵扫描是否有硬件问题
2、程序调试
重点就是这个部分,很多程序就是在调试过程中慢慢完善,先前所完成的程序部分只能算一个基本框架,当然,这一切是建立在硬件没用问题的基础上
程序在进行调试时,可以像硬件一样使用分模块调试,这样可以最迅捷的找出问题所在,不受其他模块的影响
我们在硬件调试时,一开始时51芯片不工作,经过反复检查后发现原来51芯片的31脚(/EA/VPP)必须接入高电平才能使单片机在读取程序时优先访问内部程序存储器,否则只访问外部程序存储器,而我们的程序是在内部的,故芯片不工作,我们随即在31脚外接VCC和限流电阻,在解决了这个后,硬件OK了。
软件调试时问题就比较多了,很多都是小问题,大多是因为在编写程序时一些地方不够注意或笔误引起的,在这里就不过多解释,少部分是一些难以解决的大问题,一是在输入数字的储存上,开始打算只使用一个数组str[]解决,但在编程时发现在数字转换为一个一个的编码中发现直接引用会引起数据混乱,最后在添入另一数组str1[]后问题得到解决;二是输入数据在内部进行加减乘除时,加法乘法没有错误,但减法除法因为一次输出和二次输入数据的位置关系导致第二次运作时出现错误,最后我们调整了储存数据的变量,这个问题顺利的解决了,最后一个问题困扰我们最久,甚至导致调试过程一度中止,由于我们是6位数的运算,在数字显示过程中,出现了跳位现象,比如你输入123,当输如12时,数码管正常显示12,但将3输入后,数码管显示变为了312,由于一直找不出原因,这个问题一直得不到解决,最后我尝试改变display()函数和大循环中函数的位置循序后才能正常显示,但这从理论上说不通,最后得出可能是受到延时函数delay()的延时影响,导致数码管动态显示位码出错。
在将这个问题解决后,我们的程序就基本调试完成了,但这并不是最终结果,我将做好的计算器给其他同学进行操作,在他们找茬似的操作中,我们又发现了几个隐藏的很深的BUG并加以解决,虽然不知道还有什么BUG没发现,但至少在BUG发现之前,我们的程序是没问题了。
五、设计总结
从这次课题设计任务中,我们学习到了很多,经过我们四个的共同努力,老师的精心指导,还有和在网上找到的一些资料,主要让我们掌握了数码管移位动态扫描显示的编程方法,掌握了矩阵扫描的编程方法,掌握了数据在内部运算的编程方法,这也是编程必须掌握的知识。
当然调试的时候你也是一个重点,也让我们收获良多,这其中就分硬件和软件两部分,硬件只要我们注意一些焊接问题,对板子输入简单的程序进行检测。
这个只要自己细心一点都可以按照原理图做好,其中最重要,最麻烦,也是学到和掌握的东西最多的地方就是软件调试了,这其中包括程序的编写检验,这样你必须对程序的每部分都很熟悉,掌握每句程序的再整个整体的作用。
这样你出现问题是你才能根据问题改变程序内容而达到目的。
我们出问题最多的也是这个地方,这证明了我们对程序的掌握还有欠缺,不能熟悉的掌握和运用程序,所以导致我们不能很快很好的完成课题任务。
当然也还有很多细节方面和人工的失误问题,我们几个第一次的配合还是不能很好的进行。
程序编写上也出现了很多细节的错误,并不能把程序依次性就编写好,这也浪费了我们很多的时间,这主要也是我们没有把这方面的知识学扎实。
所以我们要把一次课题设计好,不但要学习好课堂的知识,而且要注意各方面的细节。
这次课题设计使我们各方面都得到了一定的锻炼。