嵌入式单片机实习报告.docx
《嵌入式单片机实习报告.docx》由会员分享,可在线阅读,更多相关《嵌入式单片机实习报告.docx(19页珍藏版)》请在冰豆网上搜索。
嵌入式单片机实习报告
嵌入式系统综合设计实习报告
实验三
电子时钟设计
信息科学与工程学院
计本08-1班
3081817106
詹萍
同组成员:
张慧子
指导老师:
金红张飙蒋存波
目录
一、引言3
1、课题设计背景与动机3
2、课题设计的前期准备工作3
二、课程设计3
1、基本原理3
2、原理框图4
3、硬件电路原理图4
4、软件设计6
5调试过程15
三、实习总结16
一、引言
1、课题设计背景与动机
单片机系统作为一种典型的嵌入式系统,其系统设计包括硬件电路设计和软件编程设计两个方面,其调试过程一般分为软件调试、硬件测试、系统调试3个过程。
电子钟在工业控制和日常生活中是很重要的,它不仅可以用于计时、提醒又可用于对机器的控制,在自动化的过程中必然有电子钟的参与,因此电子钟的应用会越来越广泛。
而且向着精确、低功耗、多功能发展。
基于单片机设计的数字钟精确度较高,因为在程序的执行过程中,任何指令都不影响定时器的正常计数,即便程序很长也不会影响中断的时间。
从而,使数字钟的精度仅仅取决于单片机的产生机器周期电路和定时器硬件电路的精确度。
另外,程序较为简洁,具有可靠性和较好的可读性。
如果我们想将它应用于实时控制之中,只要对上述程序和硬件电路稍加修改,便可以得到实时控制的实用系统,从而应用到实际工作与生产中去。
利用单片机实现的电子钟具有编程灵活,便于功能扩充,精确度高等特点。
2、课题设计的前期准备工作
采用AT89C52芯片,它除了具备AT89C51的所有功能与部件外,其最大的优势就是AT89C52提供了8K字节可擦写Flash闪速存储器空间、8个中断源、及256*8字节内部存储器(RAM),解决了我们对可反复擦写的Flash闪速存储器空间大小与中断源的不够问题的担心。
采用LCD,电路比较简单,且在软件设计上也相对简单,具有低功耗功能,能够满足设计最优的要求。
直接采用单片机定时计数器提供的秒信号,使用程序实现年、月、日、时、分、秒计数。
采用此种方案可减少芯片的使用,节约成本,实现的时间误差较小,但程序设计较为复杂。
我们小组查阅了大量相关的软件设计资料与数据手册,为硬件和软件的设计做了提前的准备。
二、课程设计
1、基本原理
本电子钟采用AT89C52单片机为核心,使用晶振与单片机AT89C52相连接,以LCD显示年、月、日、时、钟和秒的要求。
该电子钟设有五个按键S1、S2、S3、S4和RESET键,进行相应的操作就可实现校时、复位功能。
在中断程序中主要实现年、月、日、时、分、秒的计时功能,根据设计的要求需要60秒向分进一位,60分向时进一位,24小时向日进一位,超出本月最大日数向月进一位并将日值改为1,达到13个月后向年进一位并将月值改为1,年的显示范围为0000~9999。
定时器T0和T1有4种工作方式,即方式0、方式1、方式2、方式3。
各种凡是的选择是通过对TMOD的M1、M0两位进行编码来实现的。
在本程序中,只选用了一个定时器T0,根据设计的要求选择TMOD的工作方式为方式1。
在主程序中设定一个初值为20的软件计数器使定时器T0工作于方式1定时50ms,这样每当T0到50ms时,CPU就响应它的溢出中断请求,进入它的中断服务子程序。
定时器的最大定时时间为50ms,因此如果想得到1s的定时,需要计20次50ms才能实现。
故T0工作于方式1,定时20次,就可以定时1s了。
2、原理框图
3、硬件电路原理图
本设计的硬件系统主要由以下几个模块来实现,控制器模块、输入模块、输出模块、电源模块。
控制器模块主要用于对按键信号的接受和处理,控制液晶显示。
输入模块主要用于向控制器模块输入各种信息。
输出模块主要用于实时的显示各种信息。
电源模块主要用于向整个硬件系统供电。
控制器模块AT89C52
AT89C52的内核和AT51系列单片机一样,故引脚也相同:
1~8:
I/OP1口(P1.0~P1.7);
9:
复位脚(RST/Vpd);
10~17:
I/OP3口(P3.0=RXD,P3.1=TXD,P3.2=-INT0,P3.3=-INT1,P3.4=T0,P3.5=T1,P3.6=-WR,P3.7=-RD)主要是此引脚;
18、19:
晶振(18=XTAL2,19=XTAL1);
20:
地(Vss);
21~28:
I/OP2口(P2.0~P2.7);
29:
-PSEN;
30:
ALE/-PROG;
31:
-EA/Vpp
32~39:
I/OP0口(P0.7~P0.0);
40:
+5V电源。
注:
引脚功能前加“-”,说明其是低电平有效。
输入模块MAX232
第一部分是电荷泵电路。
由1、2、3、4、5、6脚和4只电容构成。
功能是产生+5v和-5v两个电源,提供给RS-232串口电平的需要。
第二部分是数据转换通道。
由7、8、9、10、11、12、13、14脚构成两个数据通道。
其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。
8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。
TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DB9插头;DB9插头的RS-232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。
第三部分是供电。
15脚GND、16脚VCC(+5v)。
电源模块DS18B20
1接地,2接数据线,3接电源
输出模块LCD1602
4、软件设计
(1)流程图
内部中断流程图
LCD液晶显示流程图加减子程序流程图
主程序流程图
本设计的软件系统主要采用以下基本模块来实现,主程序,中断服务程序,键盘扫描程序和液晶显示程序。
主程序用于对各功能程序模块的运用及控制。
中断服务程序用于电子钟的运行。
键盘扫描程序用于确定按键并进行相应处理。
液晶显示程序用于控制液晶的显示。
(2)代码附录
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitrs=P2^6;
sbitrw=P3^6;
sbitlcden=P2^5;
sbits1=P3^2;//模式键
sbits2=P3^3;//增加键
sbits3=P3^4;//减少键
sbits4=P3^5;//确定键
ucharcount,s1num;
charmiao,fen,shi,ri=1,yue=12,nian=10,nian_h=20,j,k,l;
ucharcodetable1[]="D:
2010-12-01";
ucharcodetable2[]="T:
00:
00:
00";
ucharcodetable3[]="DigitalClock";
voiddelay(uintz)//延时程序
{uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);}
voidwrite_com(ucharcom)//向1602液晶写命令
{rw=0;rs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}
voidwrite_date(uchardate)//向1602液晶写数据
{rw=0;rs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}
voidinit()//初始化
{ucharnum;
lcden=0;
write_com(0x38);//设置显示模式
write_com(0x0c);//开显示
write_com(0x06);//当写时光标自动加1
write_com(0x01);//清屏显示
write_com(0x80);//数据指针设置
for(num=0;num<16;num++)
{write_date(table3[num]);
delay(168);}
TMOD=0x01;//设置定时工作方式1
TH0=(65536-50000)/256;//定时器装初置
TL0=(65536-50000)%256;
EA=1;//开总中断
ET0=1;//开T0定时器中断
TR0=1;//启动定时器
}
voidwrite_nyr(ucharadd,uchardate)//写年,月,日
{ucharshi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
voidwrite_sfm(ucharadd,uchardate)//写时分秒
{ucharshi,ge;//设定个位,十位变量
shi=date/10;//分出十位
ge=date%10;//分出个位
write_com(0x80+0x40+add);//定位设置
write_date(0x30+shi);//十位数据
write_date(0x30+ge);//个位数据
}
ucharleap(ucharnian)//判断是否闰年并返回二月份的天数
{//闰年返回29,平年返回28
nian+=nian_h*100;
if(nian%4==0)
{if(nian%100==0)
{if(nian%400==0)
return29;
elsereturn28;
}
elsereturn29;
}
elsereturn28;
}
ucharmon(ucharyue)//计算并返回每个月的天数
{switch(yue)
{case1:
case3:
case5:
case7:
case8:
case10:
case12:
return31;break;
//1,3,5,7,8,10,12月每月31天
case4:
case6:
case9:
case11:
return30;break;
//4,6,9,11月每月30天
case2:
returnleap(nian);break;//返回二月份的天数
default:
break;
}
}
voidkeyscan()//键盘扫描程序
{ucharnum;
if(s1==0)//如果S1键按下
{delay(5);//消抖
if(s1==0)//如果S1键按下
{s1num++;
while(!
s1);//判断S1键是否抬起,如果抬起,则进入设置状态
if(s1num==1)
{write_com(0x01);
write_com(0x80);
for(num=0;num<16;num++)
{write_date(table1[num]);
delay(3);}
write_com(0x80+0x40);//写命令
for(num=0;num<16;num++)
{write_date(table2[num]);//写数据
delay(3);}
TR0=1;
}
if(s1num%7==2)//如果此数为2,则执行内程序
{TR0=0;//关闭定时器
write_com(0x80+0x40+10);//设置光标在秒位置
write_com(0x0f);//设置光显示并闪烁}
if(s1num%7==3)//如果此数为3,则执行内程序
{write_com(0x80+0x40+7);}
if(s1num%7==4)
{write_com(0x80+0x40+4);}
if(s1num%7==5)
{write_com(0x80+0x0a);}
if(s1num%7==6)
{write_com(0x80+0x07);}
if(s1num%7==0)
{write_com(0x80+0x04);}
}
}
if(s1num>=2)
{if(s2==0)
{delay(5);
if(s2==0)
{while(!
s2);
if(s1num%7==2)//如果此数为2,则执行内程序
{miao++;
if(miao==60)//秒满60
{miao=0;
fen++;
if(fen==60)//分满60
{fen=0;
shi++;
if(shi==24)//时满24
{shi=0;
ri++;
if(ri=mon(yue)+1)//日超过本月最大天数
{ri=1;
yue++;
if(yue==13)//月超过12
{yue=1;
nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}
write_nyr(0x04,nian);}
write_nyr(0x07,yue);}
write_nyr(0x0a,ri);}
write_sfm(4,shi);}
write_sfm(7,fen);}
write_sfm(10,miao);
write_com(0x80+0x40+0x0a);}
if(s1num%7==3)//如果此数为3,则执行内程序
{fen++;
if(fen==60)
{fen=0;
shi++;
if(shi==24)
{shi=0;
ri++;
if(ri==mon(yue)+1)
{ri=1;
yue++;
if(yue==13)
{yue=1;
nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}
write_nyr(0x04,nian);}
write_nyr(0x07,yue);}
write_nyr(0x0a,ri);}
write_sfm(4,shi);}
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num%7==4)
{shi++;
if(shi==24)
{shi=0;
ri++;
if(ri==mon(yue)+1)
{ri=1;
yue++;
if(yue==13)
{yue=1;
nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}write_nyr(0x04,nian);}
write_nyr(0x07,yue);}
write_nyr(0x0a,ri);}
write_sfm(4,shi);
write_com(0x80+0x40+4);}
if(s1num%7==5)
{ri++;
if(ri==mon(yue)+1)
{ri=1;
yue++;
if(yue==13)
{yue=1;
nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}
write_nyr(0x04,nian);}
write_nyr(0x07,yue);}
write_nyr(0x0a,ri);
write_com(0x80+0x0a);}
if(s1num%7==6)
{yue++;
if(yue==13)
{yue=1;
nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}write_nyr(0x04,nian);}
write_nyr(0x07,yue);
write_com(0x80+0x07);}
if(s1num%7==0)
{nian++;
if(nian==100)
{nian=0;
nian_h++;
if(nian_h==100)
nian_h=99;
write_nyr(0x02,nian_h);}
write_nyr(0x04,nian);
write_com(0x80+0x04);}}}
if(s3==0)//如果S3键按下
{delay(5);
if(s3==0)
{while(!
s3);
…………
//方法同S2键按下时,故不累述
…………}}
if(s4==0)//如果S4键按下
{delay(5);
if(s4==0)
{while(!
s4);
s1num=1;
write_com(0x0c);//关闭光标显示
TR0=1;//启动定时器}}}}
voidmain()//主程序
{init();
while
(1)
{keyscan();
}
}
voidtimer0()interrupt1//中断
{TH0=(65536-50000)/256;//定时器装初置
TL0=(65536-50000)%256;
count++;
if(count==20)
{count=0;
miao++;
if(miao==60)//秒满60
{miao=0;
fen++;
if(fen==60)//分满60
{fen=0;
shi++;
if(shi==24)//时满24
{shi=0;
ri++;
if(ri=mon(yue)+1)
{ri=1;
yue++;
if(yue==13)
{yue=1;
nian++;
if(nian==100)
nian=0;
nian_h--;
if(nian_h==-1)
nian_h=0;
write_nyr(0x02,nian_h);
write_nyr(0x04,nian);}
write_nyr(0x07,yue);}
write_nyr(0x0a,ri);}
write_sfm(0x04,shi);}
write_sfm(0x07,fen);}
write_sfm(0x0a,miao);
}
}
5、调试过程
(1)测试数据
单片机上电后LCD显示器第一行依次出现字符串”DigitalClock“,第二行开始计时。
按键S1进入时间设置,按S2加,按S3减,按S4保存修改结果,启动计时器,回到计时状态。
连续按S2使秒针达到60则自动分针加1,秒针恢复为0;连续按S3使秒针达到0则自动分针减1,秒针变为59;根据平年闰年区分2月为29或28天,1、3、5、7、8、10、12月为31天;4、6、9、11月为30天。
(2)数据分析
根据延时程序把数据和命令逐个放入地址中,用LCD显示的命令控制在LCD第一行的地址依次显示预先设置的字符串“DigitalClock”,
在设置时间时中断计时器,等到按下S4时才保存修改结果,从新的设置时间开始继续计时。
按复位键,电子钟初始化并启动定时器,LCD显示器第一行显示开机代码:
“DigitalClock”;第二行显示时钟时间;
按s1键,LCD显示器第一行显示日期;第二行显示时间。
当秒达到60秒后向分进一位,当分达到60分后向时进一位,当时达到24小时后向日进一位,当日超出本月最大日数后向月进一位并将日值改为1,当月达到13后向年进一位并将月值改为1,年的显示范围为0000~9999;
再次按s1键,电子钟产生外部中断,光标置于秒处,开始设置时间;
依此类推,多次按动s1键,光标依次置于时、日、月、年处,设置时间;
再次按动s1键,光标回到秒处;
光标出现后,按s2键,光标所在处的数值加1,当达到上限值后,按照步骤3方式产生进位;
光标出现后,按s3键,光标所在处的数值减1,当达到下限值后,退位。
原理同步骤3。
;
按s4键,光标消失,以设置后的时间为初始值启动定时器。
三、实习总结
1、实习中的经验
老师上课讲的实验时必须注意的几点非常重要,例如电路板和手掌的静电,启动电源开关对端口的影响,芯片的保护等等。
这些都是日后我们实习或者做实验中必须注意的,否则对实验器件都有损坏的影响。
单片机是计算机技术,大规模集成电路技术和控制技术的综合产物。
现在,单片机早已成为人类生活中不可或缺的助手。
作为本专业的核心课程之一,我意识到,要学好单片机,不仅要在理论上弄清其工作