单片机计算器的课程设计报告.docx

上传人:b****5 文档编号:4829921 上传时间:2022-12-10 格式:DOCX 页数:29 大小:547.79KB
下载 相关 举报
单片机计算器的课程设计报告.docx_第1页
第1页 / 共29页
单片机计算器的课程设计报告.docx_第2页
第2页 / 共29页
单片机计算器的课程设计报告.docx_第3页
第3页 / 共29页
单片机计算器的课程设计报告.docx_第4页
第4页 / 共29页
单片机计算器的课程设计报告.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

单片机计算器的课程设计报告.docx

《单片机计算器的课程设计报告.docx》由会员分享,可在线阅读,更多相关《单片机计算器的课程设计报告.docx(29页珍藏版)》请在冰豆网上搜索。

单片机计算器的课程设计报告.docx

单片机计算器的课程设计报告

3.5按键监视电路…………………………………………………5

附录3、器件清单……………………………………………………24

 

一、设计任务和性能指标

1.1设计任务

自制一个单片机最小系统,包括复位电路,采用外部小键盘输入数据,能够实现加法、乘法及一个科学计算,计算结果显示在四位一体的数码管上。

要求用Protel画出系统的电路原理图(要求以最少组件,实现系统设计所要求的功能),印刷电路板(要求布局合理,线路清晰),绘出程序流程图,并给出程序清单(要求思路清晰,尽量简洁,主程序和子程序分开,使程序有较强的可读性)。

1.2性能指标

1.加法:

四位加法,计算结果若超过四位则显示计算错误;

2.减法:

四位减法,计算结果若小于零则显示计算错误;

3.乘法:

个位数乘法;

4.除法:

整数除法;

5.取对数;

6.开平方;

7.指数运算;

8.有清零功能

二.设计方案

按照系统设计的功能的要求,初步确定设计系统由主控模块、监测模块、显示模块、键扫描接口电路共四个模块组成,电路系统构成框图如图1.1所示。

主控芯片使用51系列AT89C52单片机,采用高性能的静态80C51设计,由先进工艺制造,并带有非易失性Flash程序存储器。

它是一种高性能、低功耗的8位COMS微处理芯片,市场应用最多。

监测模块采用二极管和扬声器(实验室用二极管代替)组成电路。

键盘电路采用4*4矩阵键盘电路。

显示模块采用4枚共阳极数码管和74ls273锁存芯片构成等器件构成。

整个单片机的接口电路:

P0用于显示输出;

P1用于键扫描输入;

P2用于数码管位选控制;

P3用于键盘扩展(部分运算符输入);

三.系统硬件设计

3.1单片机最小系统

单片机最小系统就是支持主芯片正常工作的最小电路部分,包括主控芯片、复位电路和晶振电路。

主控芯片选取STC89C52RC芯片,因其具有良好的性能及稳定性,价格便宜应用方便。

晶振选取11.0592MHz,晶振旁电容选取20pF。

采用按键复位电路,电阻分别选取100Ω和10K,电容选取10μF。

以下为单片机最小系统硬件电路图。

单片机最小系统硬件电路

3.2键盘接口电路

计算器所需按键有:

数字键:

’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’,’0’

功能键:

’+’,’-‘,’*’,’/’,’=’,’C(清零)’

扩展键:

“log”,“ln”,“x^2”“小数点”,“开方”

共计25个按键,采用4*4矩阵键盘,键盘的行和列之间都有公共端相连,四行和四列的8个公共端分别接P1.0~P1.7,这样扫描P1口就可以完成对矩阵键盘的扫描,通过对16个按键进行编码,从而得到键盘的口地址,对比P1口德扫描结果和各按键的地址,我们就可以得到是哪个键按下,从而完成键盘的功能。

以下为键盘接口电路的硬件电路图

键盘接口电路

实物图:

扩展键接口电路:

3.3数码管显示电路

采用8位数码管对计算数据和结果的显示(实验时只用到了4位),这里选取共阴数码管,利用74LS244N对数码管进行驱动,为了节省I/O资源,采取动态显示的方法来显示计算数据及结果。

P0口输出显示值,

P2.0~P2.7(实际操作用到P2.0-P2.3)用来作为位选端,控制哪几位数码管进行显示。

以下为数码显示电路的硬件电路图

74LS244N接口电路:

3.4按键监视电路

按键监视电路就是在按键时,发出声音提醒,以确保输入数字有效。

这里就采用5V蜂鸣器作为示音设备(实际操作用发光二极管代替)。

用p3.7口输出信号。

以下为报警电路硬件电路图

按键监视电路图

系统整体硬件电路图见附录一

四、系统软件设计

4.1键盘扫描子程序设计

要进行数据的计算就必须先进行数据的输入,也就必须确定按键输入的数值是什么,这就需要对键盘进行扫描,从而确定究竟是哪个键按下。

以下为键盘扫描子程序的程序清单。

ucharKeyscan(void)

{

uchari,j,temp,Buffer[4]={0xef,0xdf,0xbf,0x7f};

for(j=0;j<4;j++)

{

P1=Buffer[j];

/*以下三个_nop_();作用为让P1口的状态稳定*/

delay();

temp=0x01;

for(i=0;i<4;i++)

{

if(!

(P1&temp))

{

return(i+j*4);

}

temp<<=1;

}

}

}

4.2移位程序及结果计算代码设计

输入数据要存储在一四位数组内,而我们键入的值是数据的高位,后键入的值是低位,这样我们就需要在输入低位数值时将高位数值从数组的低位移向数组的高位,这就是编写移位子程序的目的。

对于结果计算子程序,包含加、减、乘、除四种运算。

以加法运算为例,各种运算各有其标志位来代表计算类型,当加法标志位add=1是,就将输入的两个数据按照加法进行计算。

首先将数组内的数按照对应的位关系,将其转化为一个十进制数,这样我们就得到了加速和被加数这样俩个十进制数,从而我们就可以简单的将两个数进行相加,结果就是我们所求的数值。

但这个数值不能直接显示到数码管上,我们还要对其进行处理,使其变为对应进位的四个数存入数组内,以便显示。

既通过对结果数值分别除以1000、100、10和对10取余,得到我们想要的四个数,送显示子程序显示。

其余减、乘、除的计算方法与加法的计算方法一样,这里不再累述。

以下为移位子程序和结果计算子程序的程序清单。

这部分嵌入到了主函数中。

调用输入数据函数:

4.3显示子程序设计

从始至终无论是输入的计算数据,还是计算后的结果值。

都存储在同一数组dat[]中,这样我们只要在显示时一直调用dat[]中的值,就能正确的显示数据。

以下为显示子程序的程序清单。

voiddiaplay(void)interrupt1

{

ucharlen;

TH0=(65536-2000)/256;

TL0=(65536-2000)%256;

P2=Disbuf[dcounter];

len=dcounter;

P0=xx[len];

dcounter+=1;

if(dcounter==8)

{

dcounter=0;

}

}

延时程序:

voidDelay_1ms(uinti)//1ms延时

{

ucharx,j;

for(j=0;j

for(x=0;x<=148;x++);

}

 

voiddelay()

{

inti,j;

for(i=0;i<=10;i++)

for(j=0;j<=2;j++)

;

}

 

4.4主程序设计

主程序既把以上各子程序串连成一个整体,使整个程序循环运行。

而在以上程序中也已经加入了个程序之间的连接点,首先进入程序后就立即进入显示子程序,而显示子程序内又调用键盘扫描子程序,若有键按下,则会跳转到移位子程序和结果计算子程序进行相应的处理。

通过计算或移位后,数组内的值发生改变,显示的值也会同时发生改变。

之后再进行键盘扫描,如此反复运行,就构成了程序的整体。

整体程序清单如下:

#include

#include

#include

typedefunsignedcharuchar;

typedefunsignedintuint;

voiddelay();

ucharKeyscan(void);

voidresult_a(void);

voiddiaplay(void);

voidDelay_1ms(uinti);

ucharvie_a[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

ucharexchg_a[16]={7,8,9,13,4,5,6,12,1,2,3,11,14,0,15,10};

ucharxx[8];

ucharxxu[8];

voidSpeak_a(void);

sbitspp=P3^7;//响铃

sbitcl3=P3^6;//小数点

sbitcl=P3^1;//求ln

sbitcl0=P3^2;//开方

sbitcl1=P3^3;//求log

sbitcl2=P3^4;//求e的x次幂

ucharflo[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xef,0xef};

ucharzz[8]={0x77,0x3f,0x77,0x77,0x79};

ucharDisbuf[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

ucharyy[8]={0x3f,0,0};

floata=0,b=0,c;

ucharL=1;

ucharcal_a=0,dcounter=0;

voidmain(void)

{

ucharsinglp_a=1,n=1;

ucharkey=18;

ucharall_m=0,ent_a=0,att=1;

signedlongs,r;

TMOD=0x01;

TH0=(65536-2000)/256;

TL0=(65536-2000)%256;

EA=1;

ET0=1;

TR0=1;

spp=0;

while

(1)

{

if(singlp_a==1)

{

singlp_a=0;

P3=0x7f;

if(P3!

=0x7f)

{

Delay_1ms

(2);

if(cl==0)

{

Speak_a();

cal_a=14;//求以㏑x

key=15;

}

if(cl0==0)

{

Speak_a();

cal_a=15;//开方

key=15;

}

if(cl1==0)

{

Speak_a();

cal_a=16;//求以十为底对数

key=15;

}

if(cl2==0)

{

Speak_a();

cal_a=17;//求e的x次幂

key=15;

}

if(cl3==0)

{

att=0;

xx[0]=xx[0]+0x80;

}

}

P1=0x0f;

if(P1!

=0x0f)

{

Delay_1ms

(2);

if(P1!

=0x0f)

{

key=exchg_a[Keyscan()];

Speak_a();

}

}

}

P1=0x0f;

P3=0x7f;

if(P1==0x0f&&P3==0x7f)

{

singlp_a=1;

}

if(key<=9&&key>=0)

{

if(all_m==0)

{

if(ent_a==0)

{

uchari;

ent_a=1;

for(i=0;i<=7;i++)

{

xx[i]=0;

}

}

else

{}

if(att==1)

{

uchari;

a=a*10+key;

for(i=7;i>0;i--)

{

xx[i]=xx[i-1];

}

xx[0]=vie_a[key];

key=18;

}

else

{

uchari;

doublem;

for(i=7;i>0;i--)

{

xx[i]=xx[i-1];

}

xx[0]=vie_a[key];

m=key;

for(i=1;i<=n;i++)

{

m=m/10;

}

a=m+a;

n++;

key=28;

}

}

else

{

if(att==1)

{

uchari;

b=b*10+key;

for(i=7;i>0;i--)

{

xx[i]=xx[i-1];

}

xx[0]=vie_a[key];

key=18;

}

else

{

uchari;

doublem;

for(i=7;i>0;i--)

{

xx[i]=xx[i-1];

}

xx[0]=vie_a[key];

m=key;

for(i=1;i<=n;i++)

{

m=m/10;

}

b=m+b;

n++;

key=28;

}

}

}

if(key>=10&&key<=13)

{

uchari;

cal_a=key;

for(i=0;i<=7;i++)

{

xx[i]=xxu[i];

}

all_m=1;

key=18;

att=1;

n=1;

}

if(key==14)

{

uchari;

key=18;

ent_a=0;

for(i=0;i<=7;i++)

{

xx[i]=yy[i];

}

a=0;

b=0;

c=0;

all_m=0;

L=1;

att=1;

n=1;

cal_a=0;

}

if(key==15)

{

uchari;

all_m=0;

key=28;

for(i=0;i<=7;i++)

{

xx[i]=0;

}

result_a();//调用求计算结果

if(L==1)

{

if(c==0)

{

xx[0]=0x3f;

}

if(c>=0.0001)

{

r=c;

s=10000*(c-r);

n=0;

xx[n]=vie_a[s%10];

if(s%10!

=0)

{

n++;

}

if(c>=0.001)

{

r=c;

s=1000*(c-r);

xx[n]=vie_a[s%10];

if(n==0&&s%10==0)

{}

else

{

n++;

}

if(c>=0.01)

{

r=c;

s=100*(c-r);

xx[n]=vie_a[s%10];

if(n==0&&s%10==0)

{}

else

{

n++;

}

if(c>=0.1)

{

r=c;

s=10*(c-r);

xx[n]=vie_a[s%10];

if(n==0&&s%10==0)

{}

else

{

n++;

}

if(c>=1)

{

s=c;

xx[n]=flo[s%10];

n++;

if(c>=10)

{

s=c/10;

xx[n]=vie_a[s%10];

n++;

if(c>=100)

{

s=c/100;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=1000)

{

s=c/1000;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=10000)

{

s=c/10000;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=100000)

{

s=c/100000;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=1000000)

{

s=c/1000000;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=10000000)

{

s=c/10000000;

if(n>=8)

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=xx[i+1];

}

xx[n-1]=vie_a[s%10];

}

else

{

xx[n]=vie_a[s%10];

n++;

}

if(c>=100000000)

{

for(i=0;i<=7;i++)

{

xx[i]=zz[i];

}

}

}

}

}

}

}

}

}

}

else

{

xx[n]=0xbf;

}

}

}

}

}

}

}

}

}

voidresult_a(void)

{

switch(cal_a)

{

case0:

c=a;break;

case10:

c=a+b;break;

case11:

if(a

{

uchari;

for(i=0;i<=7;i++)

{

xx[i]=zz[i];

}

L=0;

}

else

{

c=a-b;

}

break;

case12:

c=a*b;break;

case13:

c=a/b;break;

case14:

c=log(a);

a=c;break;

case15:

c=sqrt(a);

a=c;break;

case16:

c=log10(a);

a=c;break;

case17:

c=exp(a);

a=c;break;

default:

c=0;

}

}

voidDelay_1ms(uinti)//1ms延时

{

ucharx,j;

for(j=0;j

for(x=0;x<=148;x++);

}

 

voiddelay()

{

inti,j;

for(i=0;i<=10;i++)

for(j=0;j<=2;j++)

;

}

 

ucharKeyscan(void)

{

uchari,j,temp,Buffer[4]={0xef,0xdf,0xbf,0x7f};

for(j=0;j<4;j++)

{

P1=Buffer[j];

/*以下三个_nop_();作用为让P1口的状态稳定*/

delay();

temp=0x01;

for(i=0;i<4;i++)

{

if(!

(P1&temp))

{

return(i+j*4);

}

temp<<=1;

}

}

}

voiddiaplay(void)interrupt1

{

ucharlen;

TH0=(65536-2000)/256;

TL0=(65536-2000)%256;

P2=Disbuf[dcounter];

len=dcounter;

P0=xx[len];

dcounter+=1;

if(dcounter==8)

{

dcounter=0;

}

}

voidSpeak_a(void)

{

uchari;

for(i=0;i<=20;i++)

{

spp=1;

delay();

delay();

spp=0;

delay();

delay();

}

}

五、调试及性能分析

5.1调试步骤

在焊接好器件后,先不要将芯片插在芯片座上,要先验证先板上电源是否好用,有无短路等。

接上电源,用万用表测量个芯片座对应电源和地之间的电压值,观察电压值是否正常。

一切正常后方可将芯片插入芯片座,以继续测试其他功能。

将芯片插上后,对各个模块进行调试,按键是否工作正常,数码管是否显示正常等。

编写相关部分的测试程序对其进行测试。

各部分硬件检测无误后,下载程序进行整体调试,一切正常后,结束调试过程。

在具体调试时首先遇到的问题是程序无法下载进入单片机,通过将电路板接线与原理电路图接线的对比发现,串口芯片与单片机连接的输入,输出接反,重新用铜线连接后,依然无法下载程序。

后找到原因是由于下载串口与设计封装不符,用相对应的下载线可以下载。

成功下载程序后,发现数码管显示不正确,查看后发现有先没有连接,可能是制板时漏印,连接后显示正常。

5.2性能分析

对于计算器的性能,主要的衡量指标就在于计算的精度,本次制作的计算器性能情况如下:

加法运算:

四位加法运算,和值不超过9999,若超过上限,则显示错误提示ERROR。

减法运算:

四位减法运算,若结果为负,对其取绝对值。

乘法运算:

积不超过9999的乘法运算,若超出上限,显示错误提示Error。

除法运算:

整数除法,既计算结果为整数,若除数为零,则显示错误提示Error。

通过对实际性能的分析,可以得到本次设计满足设计的要求。

六、心得体会

通过本次课程设计我真正的自己完成了对给定要求系统的硬件设计、电路设计、电路板设计、软件设计以及对成品的调试过程。

从整个过程中学习到了很多方面的知识,了解到以往学习中自己知识在某方面的不足之处,是对以往学习科目的一种贯穿和承接,从而能更好的认识和学习,也对将来从事工作大有裨益。

本次实验过程中,我切实体验到了,认真对待每一个细小零件的重要性。

对于实验室提供的零件要具有检错能力。

我做的是

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1