单片机课程设计报告.docx
《单片机课程设计报告.docx》由会员分享,可在线阅读,更多相关《单片机课程设计报告.docx(34页珍藏版)》请在冰豆网上搜索。
单片机课程设计报告
单片机课程设计报告
设计题目:
电子时钟
专业:
班级:
姓名:
陆超飞
学号:
指导教师:
评定:
设计时间:
2011年3月26日
题目:
电子时钟
一、设计目的
1、通过对电子时钟的设计,进一步熟练掌握单片机c语言的编程方法及思想。
2、通过对电子时钟的设计,掌握实时时钟ds1302及液晶显示器lm016l的使用方法。
3、通过对电子时钟的设计,进一步掌握c语言对独立式键盘的编程控制并认识独立式键盘在实际中运用。
4、通过对电子时钟的设计,增强同学们对单片机兴趣及动手能力。
并在此过程中学会对程序的逐步调试。
二、设计任务及要求
任务:
设计一个可调时的电子时钟
要求:
1、用DS1302来实现对时间的计算
2、用LM016L来显示时间
3、加独立式键盘来进行调时
三、功能描述
此时钟在正常计时模式下具有自动调整每月的天数、闰年的天数及星期的变化,而在调时模式下则不能自动调整,需操作者自行调整
时间为24小时至
MENU:
菜单按键,松开按键时有效
第一次按下此键后,进入调时状态并且秒开始闪烁,表示此时可以对秒进行修改。
以后每按一次MENU键闪烁位右移一个可调位,即以后每按一次闪烁的分别为分、时、星期、日、月、年。
INC:
加一键,松开按键有效
当MENU选中要修改的位时闪烁。
DEC:
减一键,松开按键有效
此键的操作与INC键相同,但它的作用却与INC的作用相反(即在lcd上显示出的效果正好相反),在此不再赘述
QUIT:
保存退出键,松开按键有效
按下此键松开后,会保存操作者对时钟时间的修改并退出调时模式进入正常计时状态,时间正常显示。
四、程序流程图
五.程序源代码
程序如下:
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitrs=P2^2;
sbitrw=P2^1;
sbitE=P2^0;
sbitsclk=P2^5;
sbitdata_io=P2^6;
sbitrst=P2^7;
sbits7=P0^7;
sbits0=P3^2;
sbits1=P3^3;
sbits2=P3^4;
sbits3=P3^5;
sbitbuzzer=P3^7;
ucharcodetable1[]="20//";
ucharcodetable2[]=":
:
";
ucharcodeweektable[]="MonTuesWebThurFriSatSun";
ucharcodeclocktable2[]="12:
30:
30";
ucharcodeclocktable1[]="NaoZhong:
";
ucharshi,fen,miao,month,day,week,year,qbyear=20;
ucharNshi=12,Nfen=30,Nmiao=30;
uchars0num,s3num,flag,flaga;
voidscan_key();
voidnaozhong();
voiddidi();
voidshezhinaozhong();
voiddelay_ms(uintms)
{
uinti,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
voidwrite_ds1302(ucharaddr,ucharshu)//往DS1302写数据
{
uchartemp,t;
rst=0;
sclk=0;
rst=1;
temp=addr;
for(t=0;t<8;t++)
{
if((temp&0x01)==1)
{
data_io=1;
}
else
data_io=0;
sclk=1;
delay_ms
(1);
sclk=0;
temp=temp>>1;
}
temp=shu;
for(t=0;t<8;t++)
{
if((temp&0x01)==1)
{
data_io=1;
}
else
data_io=0;
sclk=1;
delay_ms
(1);
sclk=0;
temp=temp>>1;
}
rst=0;
}
ucharread_ds1302(ucharaddr)//从DS1302读取数据
{
uchartemp,t;
rst=0;
sclk=0;
rst=1;
temp=addr;
for(t=0;t<8;t++)
{
if(temp&0x01)
data_io=1;
else
data_io=0;
sclk=1;
sclk=0;
temp=temp>>1;
}
temp=0;
for(t=0;t<7;t++)
{
if(data_io==1)
{
temp=temp|0x80;
}
else
temp=temp&0x7f;
sclk=1;
sclk=0;
temp=temp>>1;
}
returntemp;
}
voidwrite_com(ucharcom)//LCD1602的写命令
{
P1=com;
rs=0;
rw=0;
E=1;
delay_ms
(1);
E=0;
}
voidwrite_date(uchardate)//LCD1602的写数据
{
P1=date;
rs=1;
rw=0;
E=0;
delay_ms
(1);
E=1;
delay_ms
(1);
E=0;
}
voidinit()//LCD1602初始化
{
uchari;
write_com(0x38);
delay_ms
(2);
write_com(0x0c);
delay_ms
(2);
write_com(0x06);
delay_ms
(2);
write_com(0x80);
delay_ms
(1);
for(i=0;i<16;i++)
{
write_date(table1[i]);
}
write_com(0xc0);
delay_ms
(1);
for(i=0;i<12;i++)
{
write_date(table2[i]);
}
write_com(0x80+0x10);
delay_ms
(1);
for(i=0;i<10;i++)
{
write_date(clocktable1[i]);
}
write_com(0xc0+0x10);
delay_ms
(1);
for(i=0;i<12;i++)
{
write_date(clocktable2[i]);
}
}
voidwrite_sfm_10(ucharadd,uchardate)//在LCD1602写小时、分、秒
{
ucharten,ge;
ten=date/10;
ge=date%10;
write_com(0xc0+add);
write_date(0x30+ten);
write_date(0x30+ge);
}
voidwrite_nyr_10(ucharadd,uchardate)//写年、月、日
{
ucharten,ge;
ten=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+ten);
write_date(0x30+ge);
}
voidwrite_week(ucharadd,ucharweek)//写星期
{
ucharge,i;
ge=week&0x0f;
write_com(0x80+add);
if(ge==1)
{
for(i=0;i<4;i++)
{
write_date(weektable[i]);
}
}
if(ge==2)
{
for(i=4;i<8;i++)
{
write_date(weektable[i]);
}
}
if(ge==3)
{
for(i=8;i<12;i++)
{
write_date(weektable[i]);
}
}
if(ge==4)
{
for(i=12;i<16;i++)
{
write_date(weektable[i]);
}
}
if(ge==5)
{
for(i=16;i<20;i++)
{
write_date(weektable[i]);
}
}
if(ge==6)
{
for(i=20;i<24;i++)
{
write_date(weektable[i]);
}
}
if(ge==7)
{
for(i=24;i<28;i++)
{
write_date(weektable[i]);
}
}
}
voidmain()
{
init();
write_ds1302(0x8e,0x00);//打开写保护
write_ds1302(0x90,0xa7);
while
(1)
{
scan_key();//键盘扫描
if(flag==0)
{
shi=read_ds1302(0x85);//从DS1302读取时间和日期,数据为16进制
fen=read_ds1302(0x83);
miao=read_ds1302(0x81);
day=read_ds1302(0x87);
month=read_ds1302(0x89);
year=read_ds1302(0x8d);
week=read_ds1302(0x8b);
miao=(miao/16)*10+miao%16;//把16进制转化成10进制
fen=(fen/16)*10+fen%16;
shi=(shi/16)*10+shi%16;
day=(day/16)*10+day%16;
month=(month/16)*10+month%16;
year=(year/16)*10+year%16;
write_sfm_10(10,miao);//显示时间日期
write_sfm_10(7,fen);
write_sfm_10(4,shi);
write_nyr_10(9,day);
write_nyr_10(6,month);
write_nyr_10(3,year);
write_week(12,week);
}
naozhong();//闹钟功能
if(shi==Nshi&&fen==Nfen&&(miao<=Nmiao+30))
{
flaga=1;
}
if(flaga==1)
{
didi();//蜂鸣器响
}
}
}
voidscan_key()//扫描键盘
{
s7=0;
if(flaga==1)//关闭闹钟
{
if(s1==0)
{
delay_ms(10);
if(s1==0)
{
while(!
s1);
flaga=0;
}
}
if(s2==0)
{
delay_ms(10);
if(s2==0)
{
while(!
s2);
flaga=0;
}
}
}
if(s0==0)
{
delay_ms(10);
if(s0==0)
{
buzzer=0;
while(!
s0);
s0num++;
buzzer=1;
if(s0num==1)
{
flag=1;
write_com(0xc0+11);
write_com(0x0f);
shi=read_ds1302(0x85);
fen=read_ds1302(0x83);
miao=read_ds1302(0x81);
day=read_ds1302(0x87);
month=read_ds1302(0x89);
year=read_ds1302(0x8d);
week=read_ds1302(0x8b);
miao=(miao/16)*10+miao%16;
fen=(fen/16)*10+fen%16;
shi=(shi/16)*10+shi%16;
day=(day/16)*10+day%16;
month=(month/16)*10+month%16;
year=(year/16)*10+year%16;
}
if(s0num==2)
{
write_com(0xc0+8);
}
if(s0num==3)
{
write_com(0xc0+5);
}
if(s0num==4)
{
write_com(0x80+12);
}
if(s0num==5)
{
write_com(0x80+10);
}
if(s0num==6)
{
write_com(0x80+7);
}
if(s0num==7)
{
write_com(0x80+4);
}
if(s0num==8)
{
s0num=0;
write_com(0x0c);
miao=(miao/10)*16+miao%10;//10进制转16进制
fen=(fen/10)*16+fen%10;
shi=(shi/10)*16+shi%10;
day=(day/10)*16+day%10;
month=(month/10)*16+month%10;
year=(year/10)*16+year%10;
write_ds1302(0x80,miao);
write_ds1302(0x82,fen);
write_ds1302(0x84,shi);
write_ds1302(0x8a,week);
write_ds1302(0x86,day);
write_ds1302(0x88,month);
write_ds1302(0x8c,year);
flag=0;
}
}
}
if(s0num!
=0)//减键
{
if(s2==0)
{
delay_ms(10);
buzzer=0;
if(s2==0)
{while(!
s2);
buzzer=1;
if(s0num==1)
{
if(miao==0)
{
miao=60;
}
miao--;
write_sfm_10(10,miao);
write_com(0xc0+11);
}
if(s0num==2)
{
if(fen==0)
{
fen=60;
}
fen--;
write_sfm_10(7,fen);
write_com(0xc0+8);
}
if(s0num==3)
{
if(shi==0)
{
shi=24;
}
shi--;
write_sfm_10(4,shi);
write_com(0xc0+5);
}
if(s0num==4)
{
week--;
if(week==0)
{
week=7;
}
write_week(12,week);
write_com(0x80+12);
}
if(s0num==5)
{
day--;
if(year%4==0&&year%100!
=0||year%400==0)
{
if(month==2)
{
if(day==0)
{
day=29;
}
}
}
if((year%4!
=0||year%100==0)&&year%400!
=0)
{
if(month==2)
{
if(day==0)
{
day=28;
}
}
}
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
{
if(day==0)
{
day=31;
}
}
if(month==4||month==6||month==9||month==11)
{
if(day==0)
{
day=30;
}
}
write_nyr_10(9,day);
write_com(0x80+10);
}
if(s0num==6)
{
month--;
if(month==0)
{
month=12;
}
write_nyr_10(6,month);
write_com(0x80+7);
}
if(s0num==7)
{
if(year==0)
{
year=100;
qbyear--;
write_nyr_10(1,qbyear);
}
year--;
write_nyr_10(3,year);
write_com(0x80+4);
}
}
}
}
if(s0num!
=0)//加键
{
if(s1==0)
{
delay_ms(10);
buzzer=0;
if(s1==0)
{while(!
s1);
buzzer=1;
if(s0num==1)
{
miao++;
if(miao==60)
{
miao=0;
}
write_sfm_10(10,miao);
write_com(0xc0+11);
}
if(s0num==2)
{
fen++;
if(fen==60)
{
fen=0;
}
write_sfm_10(7,fen);
write_com(0xc0+8);
}
if(s0num==3)
{
shi++;
if(shi==24)
{
shi=0;
}
write_sfm_10(4,shi);
write_com(0xc0+5);
}
if(s0num==4)
{
if(week==7)
{
week=0;
}
week++;
write_week(12,week);
write_com(0x80+12);
}
if(s0num==5)
{
if(year%4==0&&year%100!
=0||year%400==0)
{
if(month==2)
{
if(day==29)
{
day=0;
}
}
}
if((year%4!
=0||year%100==0)&&year%400!
=0)
{
if(month==2)
{
if(day==28)
{
day=0;
}
}
}
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
{
if(day==31)
{
day=0;
}
}
if(month==4||month==6||month==9||month==11)
{
if(day==30)
{
day=0;
}
}
day++;
write_nyr_10(9,day);
write_com(0x80+10);
}
if(s0num==6)
{
if(month==12)
{
month=0;
}
month++;
write_nyr_10(6,month);
write_com(0x80+7);
}
if(s0num==7)
{
if(year==99)
{
year=-1;
qbyear++;
write_nyr_10(1,qbyear);
}
year++;
write_nyr_10(3,year);
write_com(0x80+4);
}
}
}
}
}
voidwrite_sfmnaozhong(ucharadd,uchardate)//显示闹钟时间
{
ucharten,ge;
ten=date/10;
ge=date%10;
write_com(0xc0+0x10+add);
write_date(0x30+ten);
write_date(0x30+ge);
}
voiddidi()
{
buzzer=0;
delay_