长沙理工大学《单片机课程设计》电子钟单片机实习报告_单片机课程设计电子钟
长沙理工大学《单片机课程设计》电子钟单片机实习报告由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“单片机课程设计电子钟”。
目录
一
引言...............................................................................................................................5
二
硬件设计.......................................................................................................................5
三
软件设计.......................................................................................................................5
四
调试过程及问题分析.................................................................................................6
五
结论.............................................................................................................................7
六
参考文献.....................................................................................................................7
附件.....................................................................................................................................8
一 引言
单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及我们生活中广泛使用的各种智能IC卡、电子宠物等,单片机都起到了举足轻重的作用。
所以单片机技术也日趋成熟。单片机是集CPU,RAM,ROM,定时,计数和多种接口于一体的微控制器。它体积小,成本低,功能强。而52系列单片机是各单片机中最为典型和最有代表性的一种。
此次单片机原理及应用实习通过利用52单片机对电子钟的设计,从而达到学习、了解单片机相关指令在各方面的应用,以及初步了解开发软、硬件的知识。
二 硬件设计
本次单片机原理及应用实习我们组用到的硬件为MCS51开发板和一个LCD12864液晶显示器。
在MCS51开发板中,对于我们组做数字电子钟而言应用到ds1302芯片,蜂鸣器,LED点阵显示屏,STC89S52单片机,锁存器等等硬件设备。
通过对这些硬件的使用实现我们组规定的以及我们拓展的要求。
三 软件设计
此次基于单片机的电子钟的实习基本要求为:
基本要求
(1)能通过键盘设定年月日时分秒;
(2)在LCD12864上显示年月日时分秒及星期;(3)整点蜂鸣器响6次,每秒响一次,最后一响是整点;(4)按学校的作息时间表定时打铃(可用一个LED灯模拟打铃)扩展要求
自动计算和显示阴历
基于这些功能,我们用到了如下程序
(1)时钟程序ds1302(2)按键控制程序keyscan
(3)整点报时程序fengming(4)作息时间表程序schooltime fengming(5)显示程序LCD12864(6)自动计算阴历程序 Chinesecalender(7)自动计算星期程序conver_week 我们最初的整体思路是将我们的实习课题分成几个模块,每个人负责一个部分,争取第一周弄完个人部分.第二周主要进行不同模块的整合,以及整个程序的调试和改进.此外准备答辩的PPT,由组长答辩。
程序设计流程图如下:
四 调试过程及问题分析
在这一次单片机原理及应用的实习中,我学到了很多。虽然整个过程并不是一帆风顺的,但是通过
我们的共同努力,最终完成了任务。充分发挥了团队精神,我们互帮互助,共同提高。
我觉得在拿到一个课题的时候,我们首先应该思考的是干什么?然后才是怎么干?最后是如何优化。于是我开始上网搜有关电子钟设计的相关资料,我了解到:我们本次是利用MCS51开发板和LCD12864液晶显示器制作的,可以完成计时、计分、几秒和校时、校分的功能。微处理器是单片机的核心,完成运算和控制的操作串行口数据存储器与复位电路、时钟电路、校时电路由微处理器控制完成各自的任务。最后通过液晶显示器显示时分秒。
在这次实习中我负责的是显示程序LCD12864,刚开始我对于LCD显示程序并不是太了解。在校园网上找到了些相关的初步显示程序。通过LCD12864中的一些程序的调用,才能进行显示,但那是以图片的形式显示的,与我们所期望的显示还是有一定的差别,所以我又做进一步的修改,通过和组员的讨论,我才知道有一个显示汉字的程序是通过字模软件实现的,之后我们的显示这一块就可以依据我们自己的想法进行设计了。
而在整个的程序综合中,也遇到了一些问题。比如在阴历显示在屏幕上的时候,最初只显示阴历两个字,不显示具体的阴历,后来经过检查发现程序调用出现问题,改正后继续进行优化。
就这样,我们反复的修改调试,最终完成了我们的整个课程设计。
五 结论
在本次的课程设计中,我们虽然走了些小弯路,但是通过我们的共同努力,最终完成了任务。我从中我学到了很多,比如团队协作精神,众人拾材火焰高。任何大问题,在一步一步细化之后,解决起来就轻松得多了!我相信只要付出了就会有收获。无论什么事情,只有当你用心去做了之后你才会发现它的真实意义所在。我觉得这一次实习是非常有意义的,不仅提高了专业素养,还培养了我们的合作精神。我要把握每一次学习的机会,认真对待,为以后的就业及更深层次的发展添砖加瓦。
六 参考文献
一、谭浩强 C语言课程设计(第三版)清华大学出版社 2005.7
二、杨恢先 黄辉先 单片机原理及应用[M] 北京人民邮电出版社 2006.10
三、C编写组编 常用C语言速查手册 龙门书局 1995
附件
*********************************初始化LCD*******************************/ void Lcminit(void){ cbyte=DISPOFF;
WrL(cbyte);
WrR(cbyte);
cbyte=DISPON;
WrL(cbyte);
WrR(cbyte);
cbyte=DISPFIRST;
WrL(cbyte);
WrR(cbyte);
Lcmcls();
Locatexy(0,0);} /***********************************LCD清屏********************************/ void Lcmcls(void){ uchar i,j;
for(i=0;i
delay(6);
for(j=0;j
delay(6);
Wrdata(0x0,i,j);
}
} }
/************************************写左区*********************************/ void WrL(uchar x){
P0=0xFF;//P0口送FF,准备读
lck = 0;
P1 = 0x2a;//ELCD=1/W=1(读),CSB=1,CSA=0
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;//ELCD=0,R/W=0(读),CSB=0,CSA=0
lck = 1;
P0 = x;
//数据送到P0口
lck = 0;
P1 = 0x22;//ELCD=1,RW = 0(写),CSB=1,CSA=0
lck = 1;
lck = 0;
P1 = 0x00;//ELCD=0,RW = 0(写),CSB=0,CSA=0
lck = 1;} /***********************************写右区***********************************/void WrR(uchar data x){
P0=0xFF;//P0口送FF,准备读
lck = 0;
P1 = 0x29;//ELCD=1,R/W=1(读),CSB=0,CSA=1
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;//ELCD=0,R/W=0(读),CSB=0,CSA=1
lck = 1;
P0=x;
//数据送到P0口
lck = 0;
P1 = 0x21;//ELCD=1,RW = 0(写),CSB=0,CSA=1
lck = 1;lck = 0;P1 = 0x00;//ELCD=0,RW = 0(写),CSB=0,CSA=0 lck = 1;
} /**********************************显示定位***********************************/ void Locatexy(uchar row,uchar col){ uchar x, y, right;
switch(col&0xc0)
{ case 0:{
P0=0xFF;//P0口送FF,准备读
lck = 0;
P1 = 0x29;//ELCD=1,R/W=1(读),CSB=0,CSA=1
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;
lck = 1;
right = 1;break;}//置右半屏标志
case 0x40:{
P0=0xFF;//P0口送FF,准备读
lck = 0;
P1 = 0x2a;//ELCD=1,R/W=1(读),CSB=1,CSA=0
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;//ELCD=0,R/W=0(读)CSB=0,CSA=0
lck = 1;
right = 0;break;}//置左半屏标志
}
x=col&0x3f|SETX;//把列数据变成行命令
y=row&0x07|SETY;//把行数据变成行命令
/****************************************************************************/
lck = 0;
if(right)
P1 = 0x29;
else
P1 = 0x2a;
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;
lck = 1;/***********************************以上为判断忙标志**************************/
P0 = y;
lck = 0;
if(right)
P1 = 0x21;
else
P1 = 0x22;
lck = 1;
lck = 0;
P1 = 0x00;
lck = 1;/************************************以上为送行命令*****************************/
P0=0xFF;
lck = 0;
if(right)
P1 = 0x29;
else
P1 = 0x2a;
lck = 1;
while(P0 & LCDBUZY);//最高位为1,表示忙,则循环
lck = 0;
P1 = 0x00;
lck = 1;/*************************************以上为判断忙标志***************************/
P0 = x;
lck = 0;
if(right)
P1 = 0x21;
else
P1 = 0x22;
lck = 1;
lck = 0;
P1 = 0x00;
lck = 1;/*************************************以上为送列命令***************************/
if(right)
statu = 1;
else
statu = 0;//置左又半区标志
} /*************************************数据写输出*******************************/ void Wrdata(uchar x,uchar row,uchar col){
Locatexy(row,col);//定位显示位置
lck = 0;
if(statu)
P1 = 0x05;//ELCD=0R/W=0(写),D/I= 1,CSB=0,CSA=1
else
P1 = 0x06;//ELCD=0,R/W=0(写),D/I= 1,CSB=1,CSA=0
lck = 1;
P0 = x;
lck = 0;
if(statu)
P1 = 0x25;//ELCD=1,R/W=0(写),D/I= 1,CSB=0,CSA=1
else
P1 = 0x26;//ELCD=1,R/W=0(写),D/I= 1,CSB=1,CSA=0
lck = 1;
lck = 0;
P1 = 0x00;
lck = 1;}
/**********************************半角数据点阵输出******************************/ void Puthalf(uchar *strch,uchar row,uchar col){
uchar i,bakerx;
bakerx = row;
for(i=0;i
{ cbyte=strch[i];
Wrdata(cbyte,bakerx,col);
cbyte=strch[i+1];
Wrdata(cbyte,bakerx+1,col);
col++;
i++;} } void Puthz(uchar *str,uchar row,uchar col){
uchar i,bakerx;
bakerx=row;
for(i=0;i
{
cbyte=str[i];
Wrdata(cbyte,row,col);
//上半字节输出
i++;
row=bakerx+1;
cbyte=str[i];
Wrdata(cbyte,row,col);
//下半字节输出
row=bakerx;
col=col+1;
} } /****************************字符型点阵行--》列转换************************/ void VtoH8x16change(uchar
*hzbuf){
uchar i,j,k, cash[16];
uchar
newbyte, savebit[8];
for(k=0;k
newbyte = 0;
for(i=0;i
savebit[i]=hzbuf[i] & 0x80;}
for(j=0;j
savebit[j] = savebit[j] >>(7-j);
newbyte = newbyte | savebit[j];}
cash[k] = newbyte;
newbyte = 0;
for(i=8;i
savebit[i-8]=hzbuf[i] & 0x80;}
for(j=0;j
savebit[j] = savebit[j] >>(7-j);
newbyte = newbyte |savebit[j];}
cash[k+1] = newbyte;
for(j=0;j
hzbuf[j] = hzbuf[j]
}
k++;}
for(i=0;i
hzbuf[i] = cash[i];} /*******************************显示英文和符号字符*******************************/ void vWrite8x16Character(uchar *ch,uchar row,uchar col,bit flag){uchar
ucXArray[16],i;
if(flag){
// 反白显示英文 for(i = 0;i
ucXArray[i] = ~ch[i];}else{
for(i = 0;i
ucXArray[i] = ch[i];}
VtoH8x16change(ucXArray);Puthalf(ucXArray,row,col);} /****************************显示中英文字符串************************************/void vWrite8x16String(uchar *str,uchar row, uchar col, bit flag){
/************************v_RTInputByte*************************/ void v_RTInputByte(uchar ucDa){
uchar i;ACC = ucDa;for(i=8;i>0;i--){ T_IO = ACC0;/*相当于汇编中的 RRC */ T_CLK = 1;T_CLK = 0;ACC = ACC >> 1;} } /********************** uchar uc_RTOutputByte*************************/
uchar uc_RTOutputByte(void){ uchar i;for(i=8;i>0;i--){ ACC = ACC >>1;/*相当于汇编中的 RRC */ ACC7 = T_IO;T_CLK = 1;T_CLK = 0;}
return(ACC);} /************************v_W1302 *************************************/
void v_W1302(uchar ucAddr, uchar ucDa){ lck = 0;P1 = 0x00;lck = 1;unsigned char i, j,thiscol;j = strlen(str);for(i = 0;i
thiscol =(i % 16)* 8 + col;//计算列地址
if(str[i]
vWrite8x16Character(&char_Table[str[i]-0x20][0],row,thiscol,flag);
}} T_CLK = 0;
lck = 0;P1 = 0x10;lck = 1;v_RTInputByte(ucAddr);/* 地址,命令 */ v_RTInputByte(ucDa);/* 写1Byte数据*/ T_CLK = 1;lck = 0;P1 = 0x00;lck = 1;}
/**************************uc_R1302***********************************/
uchar uc_R1302(uchar ucAddr){ uchar ucDa;
lck = 0;P1 = 0x00;lck = 1;
T_CLK = 0;
lck = 0;P1 = 0x10;lck = 1;v_RTInputByte(ucAddr);/* 地址,命令 */ ucDa = uc_RTOutputByte();/* 读1Byte数据 */ T_CLK = 1;lck = 0;P1 = 0x00;lck = 1;return(ucDa);}
/************************* v_Set1302 *********************************/
void v_Set1302(uchar *pSecDa){ uchar i;uchar ucAddr = 0x80;
v_W1302(0x8e,0x00);/* 控制命令,WP=0,写操作?*/ for(i =7;i>0;i--){
v_W1302(ucAddr,*pSecDa);/* 秒 分 时 日 月 星期 年 */
pSecDa++;ucAddr +=2;} v_W1302(0x8e,0x80);/* 控制命令,WP=1,写保护?*/ } /*******************************v_Get1302**************************************/
void v_Get1302(uchar ucCurtime[]){ uchar i;uchar ucAddr = 0x81;for(i=0;i
uchar temp;
copymt = 0xff;
P0=0xff;
v_Get1302(&buffer);//读取DS1302
Conver_week(0,buffer[6],buffer[4],buffer[3]);Chinesecalender(0,buffer[6],buffer[4],buffer[3]);disp = buffer[0] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],2,100,0);//秒个位
temp =buffer[0] & 0x7f;temp = temp/16;disp = temp%10 + '0';vWrite8x16Character(&char_Table[disp-0x20][0],2,92,0);//秒十位
copymt = buffer[1];
disp = buffer[1] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],2,68,0);//分个位
temp =buffer[1] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],2,60,0);//分十位
disp = buffer[2] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],2,30,0);//时个位
temp =buffer[2] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],2,22,0);//时十位
disp = buffer[3] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,100,0);//日个位
temp =buffer[3] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,92,0);//日十位
disp = buffer[4] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,68,0);//月个位
temp =buffer[4] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,60,0);//月十位
disp = buffer[6] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,30,0);//年个位
temp =buffer[6] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,22,0);//年十位
disp = buffer[7] % 0x10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,14,0);//年百位
temp =buffer[7] & 0x7f;
temp = temp/16;
disp = temp%10 + '0';
vWrite8x16Character(&char_Table[disp-0x20][0],0,6,0);//年千位
}