#define uint unsigned int #define uchar unsigned charuchar code shu[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,
0x7f,0x6f}; //0~9
uchar code shu2[]={0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd,0x87,
0xff,0xef}; //带小数点0~9
uchar code wei[]={0xef,0xdf,0xbf,0x7f,0xf7,0xfb};//数码管位选码 uchar x[]={0,0,0,0}; uchar y[]={0,0,0,0,0,0}; uint hour=12,min,sec,h=22,m=0;
uint a,s1=1,s2=1,s3=0,i=0,status=0,num=0,class=0; bit flag=0;
7
sbit P3_7=P3^7; void delay(uint t);
void keyprint(unsigned char key); void display(); void timer0();
void sint()interrupt 4 { s3++; s3=s3%4; if(RI&&s3==1) { RI=0; hour=SBUF; }
if(RI&&s3==2) { RI=0; min=SBUF; }
if(RI&&s3==3) { RI=0;
//串口中断,实现PC上快速设定时间与闹钟8
h=SBUF; }
if(RI&&s3==0) { RI=0; m=SBUF; } if(!TI) TI=0; }
void delay(uint t) { uint i; while(t--)
for(i=0;i<125;i++); }
main() {
uchar n; uchar input;
9
n=0x0f;
TMOD=0x21; TH0=(65536-5000)/256; TL0=(65536-5000)%256; TH1=0xfd; TL1=0xfd; SCON=0x50; PCON=0x00; TR1=1;
IP=0x10; TR0=1;
IE=0x92; //开定时器0,串口中断 while(1) //键扫描程序 { input=P2&0x0f;
if(input!=0x0f&&s1==1) {
delay(10);
s1=0;
if(input!=0x0f&&s2==1) {
10
s2=0; //按住不放
n = input; //n用来暂时存放键值 }
}
if(input==0x0f&&s1==0) {
s1=1;
s2=1; keyprint(n); n=0x0f;
}
if((hour==h&&min==m)||(h!=0&&min==0))
{ if(sec==0)
P3_7=0;
if(sec==1) P3_7=1; if(sec==2)
P3_7=0;
if(sec==3) P3_7=1; if(sec==4)
11
P3_7=0;
if(sec==5) P3_7=1; }
else P3_7=1; if(h>=24)
h=0;
display();
} }
void keyprint(unsigned char key) //各个按键功能 {
if(key==0x0e) {
num++; }
12
if(num==1) {class=1;} if(num==2) {class=2;num=0;}
if(key==0x0d) {
status++; if(status>=5) status=0;
}
if(key==0x0b) {
if(status==1) {
if(min<59) min++; else {min=0;hour++;}
}
if(status==2) {
if(hour<23) hour++; else hour=0;
}
if(status==3) {
if(m<59) m++;
else {m=0;h++;}
13
} }
}
if(status==4) {
if(h<23) h++; }
else h=0;
void display() //数码管数值显示函数 {
uchar d=0;
if(class==1||class==0)
{
x[0]=hour/10; // 显示时的十位 x[1]=hour%10; // 显示时的个位 x[2]=min/10; // 显示分的十位 x[3]=min%10; // 显示分的个位
while(d<4) {
P2=wei[d];
P0=shu[x[d]];
14
delay(1); d++;
}
}
else if(class==2) {
y[0]=h/10; // 显示时的十位
y[1]=h%10; // 显示时的个位 y[2]=m/10; // 显示分的十位 y[3]=m%10; // 显示分的个位
d=0; if(flag==0) {
while(d<4) {
P2=wei[d];
// 每过0.5s小数点闪烁一次
P0=shu2[y[d]]; delay(1); d++;
} }
else if(flag==1)
15
}
{
while(d<4) {
P2=wei[d];
P0=shu[y[d]]; delay(1); d++;
} }
}
void timer0() interrupt 1 //定时器0方式1中断函数 {
uint count;
TH0=(65536-5000)/256; // 定时器0设置初始值1ms中断初始值
TL0=(65536-5000)%256; TR0=1;
count++; //正常计时 if(count>=100) { flag=1;
16
if(count>=200) // 定时 1S 到,以下为时钟的正常走钟逻辑 { flag=0;
count=0;
sec++;
if(sec>= 60)
{
sec=0;
min++; //秒到60分加一,秒清零
}
if(min>= 60)
{
min=0;
} hour++;
//分到60时加一,分清零
if(hour>= 24)
{
hour=0; //时到24立即变为0 }
}
} }
17
四. 结论
4.1本次课程设计的特点:
本次课程设计对单片机这么课程的知识原理要求比较高,具有一定的编程要求。设计出的定时闹钟比较贴近生活产品,实用性计较强,因此达到了知识与实践相结合,学以致用的目的。 4.2主要贡献:
让我们再一次深入了解了单片机的基本知识和原理,给予我们一定的单片机设计经验,强化了教学目标。 4.3心得与体会:
课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。
回顾起此次单片机课程设计,我仍感慨颇多,学到了很多的东西。同时不仅巩固了以前所学过的知识,而且还学到了很多在书本上所没有学到过的知识。在实际设计中才发现,书本上理论性的东西与在实际运用中的还是有一定的出入的,所以有些问题不但要深入地理解,而且要不断地更正以前的错误思维。一切问题必须要靠自己一点一滴的解决,而在解决的过程当中你会发现自己在飞速的提升。对于单片机设计,其硬件电路是比较简单的,主要是解决程序设计中的问题,而程序设计是一个很灵活的东西,它反映了你解决问题的逻辑思维和创新能力,它才是一个设计的灵魂所在。因此可以说单片机的设计是软件和硬件的结合,二者是密不可分的。
18
五.参考文献
【1】《C51单片机技术教程》 人民邮电出版社
——田希辉、薛亮儒
【2】《单片机应用技术选编》 北京航空航天大学出版社 ——何立民
六.附 录:
1.主要使用软件:Keil C语言编写软件 Protues 仿真软件 串口调试助手
虚拟串口软件
19
2.实验箱内部图:
20