51单片机课程设计.docx
《51单片机课程设计.docx》由会员分享,可在线阅读,更多相关《51单片机课程设计.docx(28页珍藏版)》请在冰豆网上搜索。
51单片机课程设计
河南大学
单片机课程设计
设计课题:
简单计算器及七号楼自习室查询器
姓名:
刘铭、庞杰、王海云、黄彦海
学院:
物理与电子学院
专业:
测控技术与仪器
班级:
2007级一班
指导教师:
高伟
河南大学物理与电子学院测控工程系
简单计算器及七号楼自习室查询器
摘要
随着高校日益扩招,学校的自习室越来越紧张,能找到一个合适的自习室自习,已成为同学们经常谈论的话题,为此专门设计一个键盘和显示器显然大材小用,看到此种情况,我们想到了两种解决方法:
①仅通过程序,即借助同学们手机都大都带有Java扩展功能,通过现有的硬件来实现自习室的查询。
②可设计一种单片机控制的计算器通过扩展其功能实现查询功能,计算器仍是它的主要功能,这样不会增加硬件成本,仅需编写程序即可利用计算器的电路实现,我们这里仅以7号教学楼为例,如输入112代表周一的1、2节的自习室分布情况(空教室)。
这时会显示72037401。
代表本时段的空自习室为7203、7401教室,可使同学们迅捷的找到自习室。
本电路在嵌入式系统软硬件设计平台Proteus上仿真通过。
能显示所查时段五个自习室,基本上能满足同学们的需要。
目录
第一章设计任务与要求3
第二章方案的论证与选择:
3
第三章系统硬件总图及原理:
4
3.1总电路图4
3.2原理:
4
3.3.运行实际效果:
7
第四章程序设计8
4.1程序流程图:
8
4.2LCD驱动程序9
4.3计算器及自习室查询程序代码:
11
4.4自习室查询程序16
4.5键盘程序17
第五章作品改进及前景19
第六章经验心得体会19
小组成员及分工20
元件清单20
参考文献:
21
第一章设计任务与要求
随着大学的日益扩招,各个学校的自习室也逐渐紧张起来,对于勤奋的学生而言能迅速找到合适自习室,自然是一件开心的事情。
由于我们学校没有固定的自习室,故而只能利用教室没课的情况下充当自习室,而这些教室常常是变动的。
河南大学学生会制作过一份《河南大学自习室一览表》,为此我们小组认为这样一份纸制的表格,实际上可以变成一种程序,可以通过输入----查表----输出的方式实现自习室的查询。
而为了不单独增加成本,我们设计了一种兼有计算器功能的终端,使其既能作为计算器实用又能作为一个自习室查询器。
使其较高的成本能体现更多的价值。
结合当前学习的C51单片机原理,我们觉得可以通过一个计算器键盘,一个AT89C51,一个LCD显示器实现这两个功能。
①任务:
1,设计一个简易计算器。
2,通过输入有一定意义的数字代码输出相应的自习室。
3,任务分配:
刘铭070230036负责选题编程及仿真调试。
庞杰070230040负责撰写报告。
王海云070230012负责查找资料。
黄彦海070230053负责绘制硬件电路。
②要求:
1,能实现最基本的加减乘除运算(十位以内)。
2,输入制定数字时,能至少输出5个自习室供选择。
3,响应足够快
4,可以扩展其它显示功能如电子书等。
第二章方案的论证与选择:
方案一:
我们试图通过数码管显示,但是由于需要的数码管太多,即使做出来了也不方便携带,不具又便携性。
方案二:
通过12864等分辨率较小的LCD,但考虑到今后本电路可以扩展为整个金明校区的自习室显示的功能。
即显示的自习室较多,故而我们选择了分辨率较高的160128显示器。
方案三:
采用160128分辨率的显示器,并集成简易计算器功能,今后通过扩展RAM还可以实现电子书的阅读功能。
使芯片能发挥它的最大价值。
因此我们最终采用了方案三。
第三章系统硬件总图及原理:
3.1总电路图
图3-1
本电路有三部分组成,1,单片机89C51的最小系统。
2,简易计算器键盘。
3,160*128点阵的LCD(PG160128)。
3.2原理:
①先做一个简易的十位计算器。
此种电路已较为成熟,可在网上下载到,可以进行加减乘除运算,通过设计这个计算器为自习室查询器,提供好键盘电路和显示器电路。
PG160128的驱动通过搜索也可找到,我们只需解决好显示器的选择和驱动管脚连接问题。
图1-2为硬件外观图,图1-3为PG160128datasheet内容。
图3-2
图3-3
②在单片机里烧入0,1,2,3,4,5,6,7,8,9,‘~’及其它常用的字模。
以供LCD显示。
0x00,0x7c,0xc6,0xce,0xde,0xd6,0xf6,0xe6,0xc6,0x7c,0x00,0x00,//'0'
0x00,0x10,0x30,0xf0,0x30,0x30,0x30,0x30,0x30,0xfc,0x00,0x00,//'1'
0x00,0x78,0xcc,0xcc,0x0c,0x18,0x30,0x60,0xcc,0xfc,0x00,0x00,//'2'
0x00,0x78,0xcc,0x0c,0x0c,0x38,0x0c,0x0c,0xcc,0x78,0x00,0x00,//'3'
0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x1e,0x00,0x00,//'4'
0x00,0xfc,0xc0,0xc0,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,0x00,//'5'
0x00,0x38,0x60,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0x78,0x00,0x00,//'6'
0x00,0xfe,0xc6,0xc6,0x06,0x0c,0x18,0x30,0x30,0x30,0x00,0x00,//'7'
0x00,0x78,0xcc,0xcc,0xec,0x78,0xdc,0xcc,0xcc,0x78,0x00,0x00,//'8'
0x00,0x78,0xcc,0xcc,0xcc,0x7c,0x18,0x18,0x30,0x70,0x00,0x00,//'9'
0x00,0x73,0xda,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//'~'
字模的生成可由专门的生成器生成,故此电路也可显示其它字符,甚至汉字。
③对未定义键“?
”进行定义,把其定义为查询键(详细见子程序chaxun()),然后根据屏幕上输入的数字,摁下“?
”键后,如果输入的数字代码属于表1-1那么就通过程序,使LCD输出包含自习室信息的字符串。
例:
输入的为1910,就代表周一第9、10节,LCD输出“710272057401~7405”代表7102、7205和7401~7405有自习室。
数字代码及自习室对照表
数字代码
LCD输出
112
72037401
134
71027303740274037506
178
710273037503~7505
1910
710272057401~7405
11113
71027201720373017302
212
7304740174057506
234
71017203740174057504
278
71027203730375037505
2910
7101~71037301~7304
21113
7101~71037201~7203
312
71037404750275037505
334
71017103720373037402
378
7201750275037505
3910
7103720172027301~7304
31113
71017103720172037301
412
nozixishi
434
710274017403
478
7101~71037201~7205
4910
7101~71037201~7205
41113
7101~710372017203
512
73037401740575037504
534
71017102720373017303
578
71017102720172037301
5910
7101`7103720172037301
51113
71027201~72037301
612
71017102720173017303
634
71037404750275037505
678
71037404750275037505
6910
71037404750275037505
61113
71037404750275037505
712
710272017203~72057301
734
7101710272017203~7205
778
710171027201~72057301
7910
7101~71037201~7205
71113
710171037201~7205
表3-1
3.3.运行实际效果:
图3-4
我们可以看到运行结果良好,输入1910输出71027205及7401~7405。
图3-5
输入334,输出7203,7303,7402,7101,7103。
计算器的功能简单且较常见这里不再演示。
第四章程序设计
4.1程序流程图:
4.2LCD驱动程序
通过网络我们可以下载到PG160128A的驱动程序,这里我们仅给出部分显示程序。
/ASCII及汉字显示函数
uchardprintf(ucharx,uchary,char*fmt)
{
charc1,c2,cData;
uchari=0,j,uLen;
uchark;
uLen=strlen(fmt);
while(i{
c1=fmt[i];
c2=fmt[i+1];
fnSetPos(y,x/8);
if(c1>=0)
{
//ASCII
if(c1<0x20)
{
switch(c1)
{
caseCR:
caseLF:
//回车或换行
i++;
x=0;
if(y<112)y+=HZ_CHR_HEIGHT;
continue;
caseBS:
//退格
i++;
if(y>ASC_CHR_WIDTH)y-=ASC_CHR_WIDTH;
cData=0x00;
break;
}
}
for(j=0;j{
if(c1>=0x1f)
{
cData=ASC_MSK[(c1-0x1f)*ASC_CHR_HEIGHT+j];
fnSetPos(y+j,x/8);
if((x%8)==0)
{
fnPR12(LC_AUT_WR);//写数据
fnPR13(cData);
fnPR12(LC_AUT_OVR);
}
else
OutToLCD(cData,x,y+j);
}
fnSetPos(y+j,x/8);
}
if(c1!
=BS)//非退格
x+=ASC_CHR_WIDTH;
}
else
{//中文
for(j=0;j{
if(c1==GB_16[j].Index[0]&&c2==GB_16[j].Index[1])
break;
}
for(k=0;k{
fnSetPos(y+k,x/8);
if(j{
c1=GB_16[j].Msk[k*2];
c2=GB_16[j].Msk[k*2+1];
}
else
c1=c2=0;
if((x%8)==0)
{
fnPR12(LC_AUT_WR);
fnPR13(c1);
fnPR12(LC_AUT_OVR);
}
else
OutToLCD(c1,x,y+k);
if(((x+2+HZ_CHR_WIDTH/2)%8)==0)
{
fnPR12(LC_AUT_WR);
fnPR13(c2);
fnPR12(LC_AUT_OVR);
}
else
OutToLCD(c2,x+2+HZ_CHR_WIDTH/2,y+k);
}
x+=HZ_CHR_WIDTH;
i++;
}
i++;
}
returnuLen;
}
4.3计算器及自习室查询程序代码:
#include
#include
#include
externcharfnLCMInit();//LCM初始化
externvoidat(unsignedcharx,unsignedchary);/*设定文本x,y值*/
externvoidcls();//清屏
externvoidcharout(unsignedchar*str);//ASCII(8*8)显示函数
externvoidfnSetPos(unsignedcharurow,unsignedcharucol);//设置当前地址
externuchardprintf(ucharx,uchary,char*fmt);//ASCII(8*16)及汉字(16*16)显示函数
externucharfnPR12(ucharuCmd);//写无参数的指令
externucharfnPR13(ucharuData);//写数据
externvoidLine(unsignedcharx1,unsignedchary1,unsignedcharx2,unsignedchary2,bitMode);
externvoidPixel(unsignedcharPointX,unsignedcharPointY,bitMode);
sbitP1_4=P1^4;
sbitP1_5=P1^5;
sbitP1_6=P1^6;
sbitP1_7=P1^7;
sbitP3_0=P3^0;
sbitP3_1=P3^1;
sbitP3_2=P3^2;
sbitP3_3=P3^3;
sbitP3_4=P3^4;
sbitP3_5=P3^5;
ucharkey1,calc;//calc运算符号"+-*/"
uchara[15];
floatone;
ucharGeyKey();
voidadd();
voiddengyu();
voidzhengfu();
uchar*jianzero(uchar*str);
voidnumber();
voidchaxun();
voidmain()//主函数
{
ucharkey;
fnLCMInit();
fnSetPos(0,0);
key1=0;
a[0]='\0';
calc=0;
dprintf(152,0,"0");
while
(1)
{
key=GeyKey();
if(key!
=0)key1=key;
if((key==0)&&(key1!
=0))
{
if((key1>='0')&&(key1<='9')||(key1=='.'))number();//数字键
if((key1=='+')||(key1=='-')||(key1=='*')||(key1=='/'))add();//运算键加减乘除
if(key1=='=')dengyu();//等于键
if((key1=='c')||(key1=='%')||(key1=='f'))zhengfu();//正负键
if(key1=='G')chaxun();//查询键
}
}
}
uchar*jianzero(uchar*str)//去除浮点数后面多余的零
{
uchari;
i=strlen(str);
while((i>0)&&(str[i-1]=='0'))
{
str[i-1]='\0';
i--;
}
if(str[i-1]=='.')str[i-1]='\0';
returnstr;
}
voidzhengfu()//"+/-,%,on/c"键
{
floatx;
uchardsp[15];
if(key1=='c')
{
a[0]='\0';
calc=0;
cls();
dprintf(152,0,"0");
}
if(key1=='%')
{
}
if(key1=='f')
{
if((strlen(a)>0)&&(strlen(a)<10)&&(atof(a)!
=0))
{
x=atof(a);
x=x*-1;
sprintf(dsp,"%f",x);
strcpy(dsp,jianzero(dsp));
strcpy(a,dsp);
cls();
dprintf(160-strlen(dsp)*8,0,dsp);
}
}
key1=0;
}
voidadd()//加减乘除键'+-*/'
{uchardsp[15];
if(a[0]=='\0')
{
key1=0;
return;
}
if(calc!
=0)
{
switch(calc)
{
case'+':
one=one+atof(a);break;
case'-':
one=one-atof(a);break;
case'*':
one=one*atof(a);break;
case'/':
one=one/atof(a);
}
calc=key1;
key1=0;
a[0]='\0';
sprintf(dsp,"%f",one);
strcpy(dsp,jianzero(dsp));
cls();
dprintf(160-strlen(dsp)*8,0,dsp);
}
else
{
calc=key1;
key1=0;
one=atof(a);
a[0]='\0';
}
}
voiddengyu()//等于键'='
{
floatresult;
uchardsp[15];
key1=0;
if((calc==0)||(a[0]=='\0'))return;
switch(calc)
{
case'+':
result=one+atof(a);break;
case'-':
result=one-atof(a);break;
case'*':
result=one*atof(a);break;
case'/':
result=one/atof(a);
}
calc=0;
a[0]='\0';
sprintf(dsp,"%f",result);
strcpy(dsp,jianzero(dsp));
cls();
dprintf(160-strlen(dsp)*8,0,dsp);
}
voidnumber()//数字键0-9&小数点'.'
{
ucharalen;
alen=strlen(a);
if(alen==0)cls();
if((key1>='0')&&(key1<='9'))
{
if((alen==1)&&(a[0]=='0'))
{
if(key1=='0')
{
alen=0;
key1=0;
return;
}
if(key1!
='0')alen=0;
}
if(alen<10)
{
alen++;
a[alen-1]=key1;
a[alen]='\0';
}
dprintf(160-alen*8,0,a);
key1=0;
}
if(key1=='.')
{
if(strpos(a,'.')<0)
{
if((alen<10)&&(alen>0))
{
alen++;
a[alen-1]=key1;
a[alen]='\0';
dprintf(160-alen*8,0,a);
}
}
key1=0;
}
}
4.4自习室查询程序
voidchaxun()//查询程序
{uchardsp1[20];//定义字符串
ucharme[20]=”error!
”;
if(atof(a)==112)strcpy(me,"72037401");//根据输入的数字代码输出相应的字符串
if(atof(a)==134)strcpy(me,"71027303740274037506");
if(atof(a)==178)strcpy(me,"710273037503~7505");
if(atof(a)==1910)strcpy(me,"710272057401~7405");
if(atof(a)==11113)strcpy(me,"71027201720373017302");
if(atof(a)==212)strcpy(me,"7304740174057506");
if(atof(a)==234)strcpy(me,"71017203740174057504");
if(atof(a)==278)strcpy(me,"71027203730375037505");
if(atof(a)==2910)strcpy(me,"7101~71037301~7304");
if(atof(a)==21113)strcpy(me,"7101~71037201~7203");
if(atof(a)==312)strcpy(me,"71037404750275037505");
if(atof(a)==334)strcpy(me,"71017103720373037402");
if(atof(a)==378)strcpy(me,"7201750275037505");
if(atof(a)==3910)strc