基于单片机的计算机设计.docx
《基于单片机的计算机设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的计算机设计.docx(27页珍藏版)》请在冰点文库上搜索。
基于单片机的计算机设计
1系统总体方案设计
1.1课题设计任务
设计计算器,并通过SBY12864K-ZK型液晶显示,同时实现特定的功能。
通过理论设计和实物制作解决相应的实际问题,巩固和运用在《单片机技术》中所学的理论知识和实验技能,掌握单片机应用系统的一般设计方法,提高设计能力和实践动手能力,为以后从事电子电路设计、研发电子产品打下良好的基础。
1.2设计要求说明
根据所学知识,自行设计一个计算器,该计算器能够实现加减乘除四则混合运算,能够实现连续计算,并且能够实现浮点数的运算。
1.3设计课题总体方案介绍
1设计思路
本设计主要采用以下基本模块来实现,控制器模块,输入模块,输出模块。
通过对控制器进行编程。
使其对输入模块的信号进行处理计算,然后通过输出模块反馈给使用者以计算结果。
2控制部分的设计方案
用单片机实现。
由于单片机集成了运算器电路、控制电路、存储器、中断系统、定时器/计数器以及输入/输出口电路等,所以用单片机设计控制电路省去了很多分立元器件。
由于单片机是可编程芯片,并且它可以运用C语言编写,对于一些复杂的计算功能,可以调用C语言库函数。
使编写程序变得非常简单。
所以该课题用单片机实现,不仅功能易于实现,而且精确度高,稳定性好,抗干扰能力强。
并且由于其成本低、体积小、技术成熟和功耗小等优点,且技术比较成熟。
性价比也相当高。
3显示电路的设计方案
采用汉字图形液晶显示器RT12864显示方案。
RT12864M汉字图形点阵液晶显示模块,可显示汉字及图形。
供电电源为3.3V~+5V(内置升压电路,无需负压),能采用并行和串行两种通信方式。
并有光标显示、画面移位、自定义字符、睡眠模式等功能。
4键盘设计方案
4*4矩阵式键盘,这种键盘的硬件简单,使用的I/O口也不多,而且这种键盘的编程方法已很成熟。
所以本次设计采用这种矩阵式键盘。
5系统组成
确定的系统组成框图如图1-1所示。
其中单片机作为主控设备对采集输入信号后并进行处理,最后通过输出设备输出给使用者。
该系统的结构框图如图1.1。
图1.1系统结构框图
2硬件系统的设计
2.1硬件系统各模块功能简要介绍
功能芯片:
AT89S52是一种带4K字节闪烁可编程可擦除只读存储器的低电压,128字节内部RAM,32个I/O口线,2个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路,高性能CMOS8位微处理器,俗称单片机。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89S51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
AT89S52型单片机的主要性能参数如下:
1、与MCS-51产品指令系统完全兼容
2、4k字节可重擦写Flash闪存存储器
3、1000次擦写周期
4、全静态操作:
0Hz-24MHz
5、三级加密程序存储器
6、128*8字节内部RAM
7、32个可编程I/O口线
8、2个16位定时/计数器
9、6个中断源
10、可编程串行UART通道
11、低功耗空闲和掉电模式
AT89C51芯片及管脚图。
如图2.1所示。
图2.1AT89S52引脚图
时钟电路:
时钟电路用于产生单片机工作所需要的时钟信号,单片机本身就是一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地按时序进行工作。
在MCS-51芯片内部有一个高增益反相放大器,其输入端为芯片引脚X1,输出端为引脚X2,在芯片的外部跨接晶体振荡器和微调电容,形成反馈电路,就构成了一个稳定的自激振荡器。
此电路采用12MHz的石英晶体。
时钟电路如图2.2。
图2.2时钟电路
电源电路:
本电源电路是通过5V电源或采用USB接口电路进行供电。
如图2.3所示。
图2.3电源电路
复位电路:
复位是单片机的初始化操作,其主要功能是把PC初始化为0000H,使单片机从0000H单元开始执行程序。
除了进入系统的正常初始化之外,当由于程序运行出错或操作错误是系统处于死锁状态时,为摆脱困境,也需要按复位键以重新启动。
RST引脚是单片机复位信号的输入端,复位信号是高电平有效,其有效时间应持续24个振荡周期(即2个机器周期)以上,若使用频率为12MHz的晶振,则复位信号持续时间应超过4
s才能完成复位操作。
复位操作有上电自动复位和按键手动复位两种方式。
上电自动复位是通过外部复位电路的电容充电来实现的。
按键电平复位是通过使复位端经电阻与Vcc电源接通而实现的。
在本设计中采用了按键电平复位方式,其复位电路如图2.4。
图2.4复位电路
键盘电路:
本电路采用的4*4矩阵键盘,与单片机的P1口相连接,电路如图2.4所示。
图2.44*4矩阵键盘
显示电路:
RT12864M汉字图形点阵液晶显示模块,可显示汉字及图形。
与单片机接口电路如图2.5所示。
图2.6电源电路
图2.512864与单片机接口电路
2.2硬件电路元器件简介
protel原理图见附录B、PCB图见附录C、元器件布局图见附录D、元器件清单见附录E。
3软件系统的设计
3.1设计使用单片机资源的情况
单片机I/O口的使用:
P1口接矩阵式键盘,P0口、P3.0、P3.1、P3.5用于12864与单片机的连接。
3.2软件系统各模块功能介绍
(1)显示程序:
显示程序通过数码管显示器将计时时间显示出来,让大家有直观的了解。
(2)复位程序:
复位电路是程序进入默认设置状态。
(3)键扫程序:
先调键处理,再判断是否有键按下,如果没有键按下,则返回,如果有键按下,去抖延时10ms,再调键处理,如果没键按下就返回,如果有键按下,计算并保持键值,再看键是否松开,如果没松开,就再延时判断键是否松开,如果键松开,就保存键值并返回。
3.3程序流程框图
(1)系统主程序流程图
图3.1主程序流程图
(2)显示程序和键扫程序流程图
图3.2显示程序流程图图3.3键扫子程序
3.4程序清单
程序清单见附录A。
4设计结论、实验结果、误差分析、教学建议
4.1设计课题的设计结论及使用说明
该产品16个按键作为输入信号,液晶为显示器,按键功能如下图4.1所示。
0-9为数字键,a为小数点,b为等号键和清零键两种功能,c为加号键,d为减号键,e为乘号键,f为除号键。
进行计算功能时,进行相应的运算按相应的键,b键按两下进行清零。
能够实现相应的加,减,乘,除,连加,连减,连乘,连除基本运算。
能够进行浮点行运算,能够运算到小数点后四位,操作简单,给使用带来极大的方便。
图4.1键盘按键
4.2实验结果
加法运算:
图4.2加法运算
减法运算:
图4.3减法运算
乘法运算:
图4.4乘法运算
除法运算:
图4.5除法运算
连续运算:
图4.6连续运算
4.3设计课题的误差分析
由实验结果进行误差分析,由于函数中调用C语言中数学运算公式,能够正确的进行计算,有较高的精度,误差基本没有,符合设计要求。
4.4设计的重点与难点,问题的解决及不足之处,心得体会
重点:
理论与实践相结合。
Protel、keil软件的使用,实物的制作,程序的设计.
难点:
制作实物中,对硬件电路的检测,以及程序设计中数据显示,连续运算,数据处理上的问题。
解决方法:
实物制作过程中:
1、元件封装错误,需要用飞线来补救;2、由于腐蚀不完全导致电路短路,需要用刀割断;3、有断线的需要用锡丝接好;4、程序设计中,要正确定义数据类型,正确处理小数部分;5、连续运算上需要设置标志位来进行处理;6、正确应用数组来处理显示部分。
不足之处:
制作实物中,转印与腐蚀不到位造成硬件电路出现大量的短路,断路问题,程序设计上,需要灵活应用C语言函数调用。
心得体会:
通过本次的课程设计,自己在各方面都有很大的提高。
进一步加强了自己对单片机软硬件方面的了解。
单片机编程用C语言编程,需要我们对们对电路的分析,然后总结,查阅相关资料才能变成好的程序,编程讲究的是多动手写,自己写,用自己的思路,不怕写错,写错再改,懂得有新的思想这样才能提高。
同时,在这次设计需要自己能够耐心,细心。
有耐心才能够静下心来进行程序的设计,有细心才能够在做硬件电路中少出错误。
总之,在这次设计中,我学到了很多,只有经过自己的亲自动手才能体会到成功的喜悦。
4.5教学建议
首先,很感谢老师教我们单片机课程,跟着老师学到了关于单片机的很多知识,使自己在单片机的编程方面有了很大的提高,能够熟练地掌握单片机的基础知识。
在此,提出自己小小的建议,希望老师能够带领我们做更多地关于单片机方面的设计,使我们在动手动脑方面更加深一步地提高,使我们能够更加全面地掌握更多的知识,加强我们的动手能力,同时,希望老师继续您的教学风格,只有这样我们的学习积极性才高,愿意花更多地精力在学习上,使我们能够学习的更加充实。
参考文献
[1]李广弟,朱月秀,冷祖祁.单片机基础(第3版).北京:
北京航天大学出版社,2007年6月.
[2]清源计算机工作室.Protel99SE原理图与PCB及仿真.北京:
机械工业出版社出版,2007年8月.
[3]马忠梅,籍顺心,张凯,马岩(第4版).北京:
北京航天大学出版社,2007年2月.
鸣谢
感谢在暑期培训中王韧老师的指导,使我初步了解了单片机的应用,以及应用C语言进行编程,使自己在编程方面有了很大的提高。
感谢王小虎老师教授我们硬件电路的制作,使自己在这方面从生疏到能够比较娴熟地进行硬件电路的制作。
感谢吴乐老师生动有趣以及内容丰富的教学,使我对单片机有进一步深入的了解,老师在学习中的严格要求,使我们在学习上不敢松懈,不断提高自己。
最后感谢帮助我的同学。
附录A
#include
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineulongunsignedlong
typedefunsignedintuint;//枚举体
typedefunsignedcharuchar;
typedefunsignedlongunlong;
sbitrs=P3^0;//rs为‘H’,DB7——DB0显示数据;rs为‘L’,DB7——DB0显示指令数据
sbitrw=P3^1;//rw为‘H’,‘E’为‘H’,数据被读到DB7-DB0;rw为‘L’,‘E’为‘H到L’,DB7-DB0的数据被写到IR(指令寄存器)或DR(数据寄存器);
sbiten=P3^5;//使能信号端
ucharbz,v,shuzhi,aa=0,bb=0,cc,p,j=0,
print[30]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
floatk,m,ds,ds0;
bitflag1=0;
uchardisbuf[15]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
ucharcodeyejingtable[]={0x30,0x31,0x32,0x33,0x34,0x35,
0x36,0x37,0x38,0x39,0x2b,0x2d,0x78,0x2f,0x3d,0x20,0x2e};//0--9,
externvoidlcdset(void);
externvoidlcdclear(void);
externvoidcheckbusy(void);
externvoidwritecommand(ucharcommand);
externvoidwritedata(uchardata0);
externvoiddisplay(ucharx,uchary,uchar*p);//液晶显示
externvoiddelay(uint);
externucharkeyscan(void);
voidxiaoshu();
voidjishu();
voidzhixing();
voidxianshi();
voidclear();
////////////////////主函数////////////////////////////////////////voidmain()
{loop:
lcdset();
lcdclear();
display(1,3,"计算器");
while
(1)
{v=keyscan();
switch(v)
{case0x11:
shuzhi=0;if(flag1)cc++;p=0;k=k*10+p;xianshi();aa=0;break;
case0x21:
shuzhi=1;if(flag1)cc++;p=1;k=k*10+p;xianshi();aa=0;break;
case0x41:
shuzhi=2;if(flag1)cc++;p=2;k=k*10+p;xianshi();aa=0;break;
case0x81:
shuzhi=3;if(flag1)cc++;p=3;k=k*10+p;xianshi();aa=0;break;
case0x12:
shuzhi=4;if(flag1)cc++;p=4;k=k*10+p;xianshi();aa=0;break;
case0x22:
shuzhi=5;if(flag1)cc++;p=5;k=k*10+p;xianshi();aa=0;break;
case0x42:
shuzhi=6;if(flag1)cc++;p=6;k=k*10+p;xianshi();aa=0;break;
case0x82:
shuzhi=7;if(flag1)cc++;p=7;k=k*10+p;xianshi();aa=0;break;
case0x14:
shuzhi=8;if(flag1)cc++;p=8;k=k*10+p;xianshi();aa=0;break;
case0x24:
shuzhi=9;if(flag1)cc++;p=9;k=k*10+p;xianshi();aa=0;break;
case0x44:
shuzhi=16;flag1=1;xianshi();aa=0;break;//.
case0x84:
aa++;if(aa==1){shuzhi=14;zhixing();xianshi();}if(aa==2)
{lcdclear();clear();gotoloop;}break;//=
case0x18:
if(bb==0){xiaoshu();m=k;k=0;bb=1;shuzhi=10;xianshi();
flag1=0;}else{zhixing();bb=1;shuzhi=10;xianshi();}aa=0;break;//+case0x28:
if(bb==0){xiaoshu();m=k;k=0;bb=2;shuzhi=11;xianshi();
flag1=0;}else{zhixing();bb=2;shuzhi=11;xianshi();}aa=0;break;//-
case0x48:
if(bb==0){xiaoshu();m=k;k=0;bb=3;shuzhi=12;xianshi();flag1=0;}else{zhixing();bb=3;shuzhi=12;xianshi();}aa=0;break;//*
case0x88:
if(bb==0){xiaoshu();m=k;k=0;bb=4;shuzhi=13;xianshi();
flag1=0;}elsezhixing();bb=4;shuzhi=13;xianshi();}aa=0;break;default:
break;}
}
}
voidzhixing()//计算//
{xiaoshu();
switch(bb)
{case1:
ds=m+k;m=ds;k=0;break;
case2:
ds=m-k;m=ds;k=0;break;
case3:
ds=m*k;m=ds;k=0;break;
case4:
ds=m/k;m=ds;k=0;break;
default:
break;}
ds0=ds;
jishu();
}
voidjishu()//把ds0处理后放入显示缓冲区中//
{uchari;
bitj=0;
if(ds0<0){ds0=ds0*(-1);j=1;}
disbuf[0]=ds0/1000000000;
disbuf[1]=(ulong)(ds0)/100000000%10;
disbuf[2]=(ulong)(ds0)/10000000%10;
disbuf[3]=(ulong)(ds0)/1000000%10;
disbuf[4]=(ulong)(ds0)/100000%10;
disbuf[5]=(ulong)(ds0)/10000%10;
disbuf[6]=(ulong)(ds0)/1000%10;
disbuf[7]=(ulong)(ds0)/100%10;
disbuf[8]=(ulong)(ds0)/10%10;
disbuf[9]=(ulong)(ds0)%10;
disbuf[10]=16;
disbuf[11]=(ulong)(ds0*10)%10;
disbuf[12]=(ulong)(ds0*100)%10;
disbuf[13]=(ulong)(ds0*1000)%10;
disbuf[14]=(ulong)(ds0*10000)%10;
if(ds0!
=0)
{for(i=0;i<10;i++)
{if(disbuf[i]!
=0){disbuf[i-1]=15;break;}
if(disbuf[i]==0){disbuf[i]=15;
if(i==9)disbuf[i]=0;}
}
}
else{for(i=0;i<10;i++)
{disbuf[i]=15;}
disbuf[9]=0;}
if(j==1){for(i=0;i<10;i++)
{if(disbuf[i]!
=15)
{disbuf[i-1]=11;break;}
}
}
}
/////////清零函数/////////////////////////////////
voidclear()
{ucharn;
aa=0;bb=0;cc=0;flag1=0;k=0;j=0;
for(n=0;n<=30;n++)
{print[n]=15;}
}
////////////////显示函数/////////////////////////////////////////////
voidxianshi()
{uchari;
print[j++]=shuzhi;
if(aa==1){print[j++]=disbuf[i];
writecommand(0x98);
for(i=0;i<15;i++){writedata(yejingtable[disbuf[i]]);}}
writecommand(0x88);
for(i=0;i<30;i++){writedata(yejingtable[print[i]]);}
}
voidxiaoshu()//先判断k是否为小数,如果k为小数,就将k转化为小数//
{
uchari;
uintmg=1;
if(flag1){for(i=0;ik=k/(mg*1.0);}
cc=0;
flag1=0;
}
/****************判忙********************/
voidcheckbusy()
{rs=0;rw=1;en=1;
P0=0xff;//类似于键扫少了此句非常容易出错!
while
(1)
{en=1;
if(P0<0x80)break;
en=0;
}
en=0;
}
/****************写指令********************/
voidwritecommand(ucharcommand)
{checkbusy();
rs=0;
rw=0;
en=1;
P0=command;//下降沿时指令数据写入液晶
en=0;
}
/*****************写数据********************/
voidwritedata(uchardata0)
{checkbusy();
rs=1;
rw=0;
en=1;
P0=data0;//下降沿时显示数据写入液晶
en=0;}
/****************液晶工作模式设置************/
voidlcdset()
{writecommand(0x30);//基本指令集,
writecommand(0x01);//清屏DDRAM地址归零
writecommand(0x02);//地址归为
writecommand(0x0c);//显示开,光标关,反白关
writecommand(0x06);//DDRAM地址加一
}
/*******************清屏函数*********************/
voidlcdclear(void)
{writecommand(0x01);
writecommand(0x34);
writecommand(0x30);
}
/****************液晶显示*******************/
voiddisplay(ucharyy,ucharxx,uchar*p)//中文字符串以国标汉字代码存放,该代码与液晶显示代码相同,一个汉字两个字节
{switch(yy)
{case1:
writecommand(0x7f+xx);break;
case2:
writecommand(0x8f+xx);break;
case3:
writecommand(0x87+xx);break;
case4:
writecommand(0x97+xx);break;
default:
break;}
while(*p)//字符