单片机课程设计报告简易计算器源程序剖析.docx
《单片机课程设计报告简易计算器源程序剖析.docx》由会员分享,可在线阅读,更多相关《单片机课程设计报告简易计算器源程序剖析.docx(17页珍藏版)》请在冰豆网上搜索。
单片机课程设计报告简易计算器源程序剖析
宁德师范学院
单片机课程设计报告
题目
班级
姓名
学号
指导老师
设计时间
1方案设计与论证
本设计可以采用两种方案,一种是以FPGA为核心处理芯片,配备相应的外设;另外一种是以AT89S51处理器,配备相应的外设。
方案一:
采用FPGA控制
FPGA是一种高密度的可编程逻辑器件,自从Xilinx公司1985年推出第一片FPGA以来,FPGA的集成密度和性能提高很快,其集成密度最高达500万门/片以上,系统性能可达200MHz。
由于FPGA器件集成度高,方便易用,开发和上市周期短,在数字设计和电子生产中得到迅速普及和应用,并一度在高密度的可编程逻辑器件领域中独占鳌头。
但是而基于SRAM编程的FPGA,其编程信息需存放在外部存储器上,需外部存储器芯片,且使用方法复杂,保密性差,而其对于一个简单的计算器而言,实用FPGA有点大材小用,成本太高。
方案二:
采用AT89S51
单片机是单片微型机的简称,故又称为微控制器MCU(MicroControlUnit)。
通常由单块集成电路芯片组成,内部包含有计算机的基本功能部件:
中央处理器CPU,存储器和I/O接口电路等。
因此,单片机只要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。
单片机广泛用于智能产品,智能仪表,测控技术,智能接口等,具有操作简单,实用方便,价格便宜等优点,而其中AT89S52以MCS-51为内核,是单片机中最典型的代表,应用于各种控制领域。
通过以上两种方案论证和比较,从设计的实用性,方便性和成本出发,选择了以AT89S52单片机作为中央处理单元进行计算器的设计,这样设计能够实现对四位加减乘除和除法四位小点数的运算。
本设计需要使用LCD液晶显示屏和编码键盘。
故选择静态显示和用编码键盘。
使用LCD液晶显示屏显示运算结果。
2硬件设计
2.1硬件资源分配
主要用到的硬件:
AT89S52LCD液晶显示屏编码键盘
硬件分配:
1、P1、P3口:
做为输出口,控制LCD液晶显示屏显示数据的结果。
2、P2口:
做为输入口,与键盘连接,实现数据的输入。
3、LCD液晶显示屏显示输出。
显示电路
图2-1系统结构框图
电源电路
键盘电路
单片机最小系统
前面叙述了该系统的设计说明,系统采用了比较简单的设计方案,所以该系统的硬件设计的总外围电路不会产生过多的干扰。
在下面的阐述中,对系统的外围电路分别予以介绍。
键盘部分采用编码键盘,显示部分采用LCD液晶显示屏完全能够很好的实现显示方面的要求。
2.2系统电路设计
2.2.1键盘电路
键盘可分为两类:
编码键盘和非编码键盘。
编码键盘是较多按键(20个以上)和专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。
通用计算机使用的标准键盘就是编码键盘。
在智能仪器中,使用并行接口芯片8279或串行接口芯片HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可在芯片资料中得到。
当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计。
非编码键盘成本低廉。
从成本角度出发,本设计选用的是非编码键盘。
如图2-2-1
图2-2-1扫描键盘电路
2.2.2显示电路
当系统需要显示少量数据时,采用LCD液晶显示屏进行显示是一种经济实用的方法。
P0口作为液晶显示的数据端口,P3.5-P3.7口作为其控制端口,控制LCD液晶显示屏显示输出数据。
最终电路如图2-2-2所示:
图2-2-2LCD液晶显示屏显示
3软件设计
3.1主程序
主程序主要是用来对LCD液晶显示屏进行初始化的。
对输入按键判断,然后进行加减乘除,最后计算出结果,显示出计算结果。
流程图如图3-1所示:
3.2子程序
3.2.1键盘扫描子程序
键盘扫描子程序,首先读出P1的低四位,然后读出P1口的高四位。
然后键值并显示缓存。
然后将键如的值转换为ASCII码然后就可以软件来设置硬件按键各个键代表的内容。
读键程序使用的是反转法读键,不管键盘矩阵的规模大小,均进行两次读键。
第一次所有行线均输出低电平,从所有读入键盘信息(列信息);第二次所有列线均输出低电平,从所有行线读入键盘信息(行信息)。
数字键按下则将相应的数字送入缓存区,功能键按下则执行相应的程序。
3.2.2显示模块子程序
显示模块程序首先要对显示模块进行初始化;然后控制光标的位置;定义液晶显示的控制端口,用SBIT指令完成;然后设置清屏、关闭显示、归位、开显示、显示位置的首地址等等。
4安装与调试
将所有的元器件摆放在好,首先焊接51单片机的底座,确定简易计算器的键盘和液晶显示的排练位置,先将51单片机的底座焊接四周的四个点固定就好,之后再随需要焊接必要的底座引脚,接着焊接比较复杂的矩阵按键,,各个按键之间的连接,使用细导线。
在使用细导线焊接两个焊点时,先将两个焊点焊上焊锡。
之后加热焊锡再将细导线接入,使之固定。
之后再将单片机的晶振和复位电路焊入单片机的地座上。
确定最小单片机系统焊接完整后再将按键扫描接在单片机的P1口,后将各个细导线按顺序分别焊到单片机的P1端口的引脚处。
再将1602液晶显示的底座焊接在电路板上的相应位置上,从单片机和电源处将细导线按顺序分别焊接到液晶显示的底座上。
将51单片机烧入C语言程序,插入电路板上,再检查电路的接线和焊点处是否有焊错和虚焊,最重要的是要检查电路是否短路。
诺是没有错误则可以通电进行测试。
首先接上电源,打开开关,在液晶显示屏上显示出“0”则表示液晶显示是正常的,如果没有显示字符等,则可以查看电路中在液晶显示的第三个引脚上的接线是否正确,可改变其电压,使1602液晶显示的字符的亮度改变。
如显示正常则可测试矩阵按键,逐个按下没个按键,观察每个按键的功能是否正确。
如果正确则调试结束。
图4-1实物图(正面)
图4-2实物图(反面)
5性能测试与结果分析
将已经焊接好的简易计算器通电后,测试计算器的最大计算值与最小计算值。
经过测试计算器的最大运算值可以是9999*9999,最小的运算值可以是0。
经过接不同的电源测试,51单片机的工作电压范围为3V~5.5V。
实物效果图如图5-1所示:
图5-1实物效果图
6心得体会
在硬件的制作过程中我走了好多的弯路,主要是在系统还没有设计很有把握就开始动手制作了。
后来发现与设计的要求还有偏差,反复的改过了几次,浪费了大量的时间和体力。
感受到设计人员要有耐心,要认真的从要求开始研究。
软件的编写过程中费了很大的力气,因为软件的编写要求很高,要很细心,一不小心就会调用错误,很深刻的体会到作为软件编程人员是绝不能粗心大意的。
一个程序的完成的速度和质量高低与细心与否有着很大联系。
编程时,我充分使用了结构化的思想。
这样因为语句较少,程序调试比较方便,功能模块可以逐一的调试,充分体现了结构化编程的优势。
当每个模块都完成时,将其功能加到一起就完成了整体的设计。
参考文献:
[1[谭浩强.C语言程序设计[M].北京:
清华大学出版社,2000
[2[靳达.求是科技.单片机应用系统开发实例导航[M].:
人民邮电出版社,2006
[3[刘守义.单片机应用技术[M].:
西安电子科技大学出版社,2001
[4[林志琦.基于PROTEUS的单片机可视化软硬件仿真[M].北京:
北京航空航天大学出版社,2006
[5[胡汉才.单片机原理及接口技术.清华大学出版社,1996
[6[徐江海.单片机实用教程[M].北京:
机械工业出版社,2007
[7]张磊.C语言程序设计[M].北京:
高等教育出版社,2005
附录:
1电路图
2实物图(正反面)
实物图(正面)
实物图(反面)
3源程序
/*
接盘按键说明:
--------------------------------------------------
|1|2|3|+|
-------------
|4|5|6|-|
-------------
|7|8|9|*|
-------------
|C|0|=|/|
--------------------------------------------------*/
//操作简介
//按第一个数,再按'+-*/',再按'='显示出结果,然后按C清屏
//加最大9999+9999=19998
//减最大9999-0=9999
//乘最大9999*9999=99980001
//除1/9=0.1111保留小数点后4位
#include
#defineuintunsignedint
#defineucharunsignedchar
//--------LCD1602-------------------
//P00-07====D0-7
sbitrs=P2^7;//指令or数据
sbitwela=P2^6;//读or写
sbitlcden=P2^5;//使能信号
//--------LCD1602-------------------
//--------KEY-----------------------
//P1口
//--------KEY-----------------------
ucharcodetable[]="";
longintdata_a,data_b;//第一个数和第二个数
longintdata_c;//计算结果
uchardispaly[10];//显示缓冲
//************************************************************************/
//描述:
延时tus函数
//************************************************************************/
voidLCD_Delay_us(unsignedintt)
{
while(t--);//t=0,退出
}
//************************************************************************/
//描述:
延时tms函数
//************************************************************************/
voidLCD_Delay_ms(unsignedintt)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<113;j++)//执行113次循环
;
}
//************************************************************************/
//描述:
1602液晶写指令
//************************************************************************/
voidwrite_com(ucharcom)//1602液晶写指令
{
rs=0;//写指令
lcden=0;//使能1602
P0=com;//写入指令com
LCD_Delay_ms
(1);//延时1ms
lcden=1;//使能1602
LCD_Delay_ms
(2);//延时2ms
lcden=0;//使能1602
}
//************************************************************************/
//描述:
1602液晶写数据
//************************************************************************/
voidwrite_date(uchardate)//1602液晶写数据
{
rs=1;//写数据
lcden=0;//使能1602
P0=date;//写入数据date
LCD_Delay_ms
(1);//延时1ms
lcden=1;//使能1602
LCD_Delay_ms
(2);//延时2ms
lcden=0;//使能1602
}
//************************************************************************/
//描述:
指定x,y写入字符函数
//************************************************************************/
voidW_lcd(unsignedcharx,unsignedchary,unsignedcharData)
{
if(y==0){write_com(0x80+x);}//第一行
else{write_com(0xc0+x);}//第二行
write_date(Data);//写入数据
}
//指定x,y写入字符串函数
voidLCD_Write_String(unsignedcharx,unsignedchary,unsignedchar*s)
{
if(y==0){write_com(0x80+x);}//第一行
else{write_com(0xC0+x);}//第二行
while(*s)//
{write_date(*s);s++;}//写入数据
}
//************************************************************************/
//描述:
初始化液晶,及画面初始化
//************************************************************************/
voidinit_lcd(void)//初始化液晶,及画面初始化
{
wela=0;//写液晶
lcden=0;//使能1602
write_com(0x38);//8位总线,双行显示,5X7的点阵字符
LCD_Delay_us(100);//延时100us
write_com(0x0c);//开显示,无光标,光标不闪烁
write_com(0x06);//光标右移动
write_com(0x01);//清屏
write_com(0x80);//DDRAM地址归0
}
//************************************************************************/
//描述:
反转法键盘扫描
//************************************************************************/
shortkeycheckdown()/*反转法键盘扫描*/
{
shorttemp1,temp2,temp,a=0xff;
P1=0xf0;/*输入行值(或列值)*/
LCD_Delay_ms(20);/*延时*/
temp1=P1;/*读列值(或行值)*/
P1=0xff;
LCD_Delay_ms(20);/*延时*/
P1=0x0f;/*输入列值(或行值)*/
LCD_Delay_ms(20);/*延时*/
temp2=P1;/*读行值(或列值)*/
P1=0xff;
temp=(temp1&0xf0)|(temp2&0xf);/*将两次读入数据组合*/
switch(temp)/*通过读入数据组合判断按键位置*/
{
case0x77:
a=0x0d;break;//按键/
case0x7b:
a=0x0e;break;//按键=
case0x7d:
a=0;break;//按键0
case0x7e:
a=0x0f;break;//按键CE
case0xb7:
a=0x0c;break;//按键*
case0xbb:
a=0x9;break;//按键9
case0xbd:
a=0x8;break;//按键8
case0xbe:
a=0x7;break;//按键7
case0xd7:
a=0x0b;break;//按键-
case0xdb:
a=0x6;break;//按键6
case0xdd:
a=0x5;break;//按键5
case0xde:
a=0x4;break;//按键4
case0xe7:
a=0x0a;break;//按键+
case0xeb:
a=3;break;//按键3
case0xed:
a=2;break;//按键2
case0xee:
a=1;break;//按键1
default:
a=0xff;
}
returna;/*返回按键值*/
}
voiddisplay_a()//显示数据a
{
dispaly[3]=data_a%10000/1000;//千
dispaly[2]=data_a%1000/100;//百
dispaly[1]=data_a%100/10;//十
dispaly[0]=data_a%10;//个
write_com(0x80+0);//显示数据a
if(data_a>999){write_date('0'+dispaly[3]);}//显示千位
if(data_a>99){write_date('0'+dispaly[2]);}//显示百位
if(data_a>9){write_date('0'+dispaly[1]);}//显示十位
write_date('0'+dispaly[0]);//显示个位
}
voiddisplay_b()//显示数据b
{
write_com(0x80+7);//第一行
dispaly[3]=data_b%10000/1000;//千
dispaly[2]=data_b%1000/100;//百
dispaly[1]=data_b%100/10;//十
dispaly[0]=data_b%10;//个
if(data_b>999){write_date('0'+dispaly[3]);}//显示千位
if(data_b>99){write_date('0'+dispaly[2]);}//显示百位
if(data_b>9){write_date('0'+dispaly[1]);}//显示十位
write_date('0'+dispaly[0]);//显示个位
}
//计算结果
voiddisplay_c(x)
{
if(data_c<100000000&&data_c>-1)//溢出时显示错误
{
dispaly[8]=data_c%1000000000/100000000;//万万
dispaly[7]=data_c%100000000/10000000;//千万
dispaly[6]=data_c%10000000/1000000;//百万
dispaly[5]=data_c%1000000/100000;//十万
dispaly[4]=data_c%100000/10000;//万
dispaly[3]=data_c%10000/1000;//千
dispaly[2]=data_c%1000/100;//百
dispaly[1]=data_c%100/10;//十
dispaly[0]=data_c%10;//个
write_com(0x80+6+0x40);//第一行
if(x==4)
{
if(data_c>99999999){write_date('0'+dispaly[8]);}//显示万万
if(data_c>9999999){write_date('0'+dispaly[7]);}//千万
if(data_c>999999){write_date('0'+dispaly[6]);}//百万
if(data_c>99999){write_date('0'+dispaly[5]);}//十万
write_date('0'+dispaly[4]);//万
write_date('.');
write_date('0'+dispaly[3]);//千
write_date('0'+dispaly[2]);//百
write_date('0'+dispaly[1]);//十
write_date('0'+dispaly[0]);//个
}
else{
if(data_c>99999999){write_date('0'+dispaly[8]);}//显示万万
if(data_c>9999999){write_date('0'+dispaly[7]);}//千万
if(data_c>999999){write_date('0'+dispaly[6]);}//百万
if(data_c>99999){write_date('0'+dispaly[5]);}//十万
if(data_c>9999){write_date('0'+dispaly[4]);}//万
if(data_c>999){write_date('0'+dispaly[3]);}//千
if(data_c>99){write_date('0'+dispaly[2]);}//百
if(data_c>9){write_date('0'+dispaly[1]);}//十
write_date('0'+dispaly[0]);//个