单片机课程设计 电子时钟 12.docx

您所在的位置:网站首页 市政工程课程设计心得体会 单片机课程设计 电子时钟 12.docx

单片机课程设计 电子时钟 12.docx

2023-03-18 22:07| 来源: 网络整理| 查看: 265

单片机课程设计 电子时钟 12.docx

单片机课程设计 电子时钟 12.docx

文档编号:10666699上传时间:2023-02-22格式:DOCX页数:18大小:120.17KB

单片机课程设计电子时钟12

JIANGSUUNIVERSITY

单片机原理及应用

课程设计

 

学院名称:

计算机科学与通信工程

专业班级:

通信工程0801

学生姓名:

学生学号:

********12

指导教师:

熊书明

2011年01月

日历时钟与键盘显示程序设计

一.设计目的:

掌握日历时钟的编程方法,了解SMBus的编程方法。

进一步掌握T0计数器的用法和中断服务的过程。

用C51语言设计一个时钟,使其有自动报时和闹铃功能,并且可以通过键盘对当前时间进行校正,可以用键盘设置闹钟时间。

二.设计要求:

1.能能在LED显示器上实现正常的时分秒计时

2.通过键盘输入当前时间,并从该时间开始计时

3.有校时、校分功能

4.有报时功能,通过指示灯表示

5.有闹时功能,闹时时间可以设定,通过指示灯表示

三.系统流程图:

四.设计和实现:

(一).键盘输入模块

1.HD7279芯片功能:

HD7279是一片具有串行接口的,可用于驱动8位共阴极式数码管(或64只独立LED)的智能显示驱动芯片,该芯片同时还可连接多达64键的键盘矩阵,单片即可完成LED显示、键盘接口的全部功能。

HD7279内部含有译码器,可直接接受BCD码或者16进制码,并同时具有两种译码方式,此外还有消隐、闪烁、左移、右移、段寻址等多种控制指令。

HD7279具有片选信号,可方便地实现多于8位的显示或多于64键的键盘接口。

2.键盘输入模块程序设计

charGetKeyValue(void)

{

charKeyValue;

if(CPT1CN&0x40)return-1;//无键按下

Send7279Byte(0x15);//发读键盘指令00010101

KeyValue=Receive7279Byte();

NOSELECT7279;//置CS高电平

returnKeyValue;

}

voidWaitKeyOff(void)

{

while(!

(CPT1CN&0x40));

}

 

voidinputnum(void)//i=5开始,输入数字xianshidisptime[5-i]i=5--0

{//fugeidertime[j]

charj,KeyValue,i;

i=5;

while

(1)

{

KeyValue=GetKeyValue();

WaitKeyOff();

if(((KeyValue%16)>=0)&&((KeyValue%16)

{

disptime[5-i]=KeyValue;

if(((disptime[0]

{Send7279Byte(0xC8+i);//

Send7279Byte(KeyValue);

NOSELECT7279;

i--;

}

}

if(i

}

for(j=0;j

{

dertime[j]=disptime[2*j]*10+disptime[2*j+1];

}

if(set1)

{

set1=!

set1;//设置时间

}

if(set2)

{

set2=!

set2;//设置时间

}

if((KeyValue%16)==0x0f)

{

set=!

set;

}

if(set)//起停*****

{

if((KeyValue%16)==0x0e)

{

set1=!

set1;//设置时间

}

if((KeyValue%16)==0x0d)

{

set2=!

set2;//设置闹钟

}

if(set1)//设置时间**********

{

DispLED("------",0);

inputnum();

for(j=0;j

{

time[j]=dertime[j];

}

}

if(set2)//设置闹钟********

{DispLED("------",0);

inputnum();

for(j=0;j

{

nowtime[j]=dertime[j];//nowtime[j]闹钟时间

}

}

}

else

{

switch(KeyValue%16)//校时

{

case1:

time[0]=(time[0]+1+24)%24;break;//校时加1

case2:

time[0]=(time[0]-1+24)%24;break;//校时减1

case3:

time[1]=(time[1]+1+60)%60;break;//校分加1

case4:

time[1]=(time[1]-1+60)%60;break;//校分减1

case0xd:

FlashLED(8);break;//暂停闪烁

default:

break;

}

}

}

}

}

(二)LED显示模块和闪烁模块

1.LED数码管工作原理及显示码:

图1这是一个7段两位带小数点10引脚的LED数码管

图2引脚定义

每一笔划都是对应一个字母表示DP是小数点.

 

数码管分为共阳极的LED数码管、共阴极的LED数码管两种。

下图例举的是共阳极的LED数码管,共阳就是7段的显示字码共用一个电源的正。

led数码管原理图示意:

图3引脚示意图

 

从上图可以看出,要是数码管显示数字,有两个条件:

1、是要在VT端(3/8脚)加正电源;2、要使(a,b,c,d,e,f,g,dp)端接低电平或“0”电平。

这样才能显示的。

共阳极LED数码管的内部结构原理图图4:

 

图4共阳极LED数码管的内部结构原理图

共阴极LED数码管的内部结构原理图:

 

图5共阴极LED数码管的内部结构原理图

LED数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数位,因此根据LED数码管的驱动方式的不同,可以分为静态式和动态式两类。

A、静态显示驱动:

静态驱动也称直流驱动。

静态驱动是指每个数码管的每一个段码都由一个单片机的I/O埠进行驱动,或者使用如BCD码二-十进位*器*进行驱动。

静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O埠多,如驱动5个数码管静态显示则需要5×8=40根I/O埠来驱动,要知道一个89S51单片机可用的I/O埠才32个呢。

故实际应用时必须增加*驱动器进行驱动,增加了硬体电路的复杂性。

B、动态显示驱动:

数码管动态显示介面是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位元选通控制电路,位元选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位元选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位元就显示出字形,没有选通的数码管就不会亮。

透过分时轮流控制各个LED数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。

在轮流显示过程中,每位元数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极体的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示资料,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O埠,而且功耗更低。

unsignedcharcodeBdSeg[]={

0x7e,0x30,0x6d,0x79,//0123

0x33,0x5b,0x5f,0x70,//4567

0x7f,0x7b,0x77,0x1f,//89ab

0x4e,0x3d,0x4f,0x47,//cdef

0x00,0x01};

/*

;b6

;----

;b1|b0|b5

;----small

;b2|b3|b4

;----.b7

*/

2.LED显示模块的程序设计

voidDispLED(char*DispBuf,charShowDot)//ShowDot显示小数点位

{

chari,ch;

ShowDot--;

for(i=0;i

{

ch=DispBuf[i];

if((ch>='a')&&(ch

{

ch-='a';ch+=0xa;

}

if((ch>='A')&&(ch

{

ch-='A';ch+=0xa;

}

Send7279Byte(0x90+5-i);//不译码

if(ch=='')

Send7279Byte(0x00);

else

if(ch=='-')

Send7279Byte(0x01);

else

{

if(ShowDot==i)

Send7279Byte(0x80|BdSeg[ch&0x0f]);

else

Send7279Byte(BdSeg[ch&0x0f]);

}

}

NOSELECT7279;//置CS高电平

}

if(set!

=1)

{

for(i=0;i

{

disptime[2*i]=time[i]/10;

disptime[2*i+1]=time[i]%10;

}

DispLED(disptime,0);//显示时间************

}

3.LED闪烁模块程序设计

voidFlashLED(unsignedcharNo)

{

chari;

Send7279Byte(0x88);//发闪烁指令

i=0x1;

while(No)//将第一位移到第No位

{

i=i

No--;

}

Send7279Byte(~i);//1闪烁

NOSELECT7279;//置CS高电平

}

(三)主函数和中断服务程序实现

1.主程序

voidmain(void)

{

charj,KeyValue;

WDTCN=0xde;

WDTCN=0xad;//关看门狗

SYSCLK_Init();//初始化时钟

Timer0_Init();//初始化定时器

PORT_Init();//初始化IO口

SPI0_Init();//初始化SPI0

CPT1CN|=0x80;//使能比较器1

REF0CN=0x03;//使能片内参考电压

DAC0CN|=0x80;//使能DAC0

DAC0H=0;DAC0L=0;

EA=1;//开中断

Delay1us(25000);//等待25ms复位时间

Send7279Byte(0xA4);//发复位指令

NOSELECT7279;

DispLED(disptime,0);//显示初始时间

while

(1)

{

KeyValue=GetKeyValue();

WaitKeyOff();

if((KeyValue%16)==0x0f)

{

set=!

set;

}

if(set)//起停*****

{

if((KeyValue%16)==0x0e)

{

set1=!

set1;//设置时间

}

if((KeyValue%16)==0x0d)

{

set2=!

set2;//设置闹钟

}

if(set1)//设置时间**********

{

DispLED("------",0);

inputnum();

for(j=0;j

{

time[j]=dertime[j];

}

}

if(set2)//设置闹钟********

{DispLED("------",0);

inputnum();

for(j=0;j

{

nowtime[j]=dertime[j];//nowtime[j]闹钟时间

}

}

}

else

{

switch(KeyValue%16)//校时

{

case1:

time[0]=(time[0]+1+24)%24;break;//校时加1

case2:

time[0]=(time[0]-1+24)%24;break;//校时减1

case3:

time[1]=(time[1]+1+60)%60;break;//校分加1

case4:

time[1]=(time[1]-1+60)%60;break;//校分减1

case0xd:

FlashLED(8);break;//暂停闪烁

default:

break;

}

}

}

}

2.中断服务程序

voidTimer0_ISR(void)interrupt1//25ms

{

inti;

TH0=0x9e;

TL0=0x58;

if(set==1)

return;

Count1ms--;//unsignedcharCount1ms会小于0,因为无符号会溢出,计数次数变大所以延迟大

if(Count1ms==0)//秒

{

Count1ms=40;

time[2]=time[2]+1;

if((time[1]==59)&&(time[2]==55))//报时功能***********

Send7279Byte(0xbf);

//闹钟功能***********

if((time[0]==nowtime[0])&&(time[1]==nowtime[1])&&(time[2]==nowtime[2]))

Send7279Byte(0xbf);

if(((time[1]*60+time[2]-nowtime[1]*60-nowtime[2])>30)&&(time[0]==nowtime[0]))

FlashLED(8);

if(time[2]>=60)//向分进位

{

time[2]=0;

time[1]=time[1]+1;

if(time[1]>=60)//向时进位

{

time[1]=0;

time[0]=time[0]+1;

if((time[1]==00)&&(time[2]==00))

FlashLED(8);

if(time[0]>=24)

{

time[0]=0;

}

}

}

if(set!

=1)

{

for(i=0;i

{

disptime[2*i]=time[i]/10;

disptime[2*i+1]=time[i]%10;

}

DispLED(disptime,0);//显示时间************

}

}

}

 

五:

运行结果和心得体会

(一)运行结果:

通过编译、链接、下载,LED显示管能够正常显示时、分、秒,时钟可以从00:

00:

00到23:

59:

59然后再到00:

00:

00。

可以正常校时。

按键盘上1按键时小时加1,按2键小时减1,按3键分钟加1,按4键分钟减1。

可以在键盘上对当前时间进行设置。

按F键,然后按E键,再从键盘键入当前时间。

当时间到**:

59:

55时LED显示管开始闪烁进行整点报时,到**:

00:

00时停止闪烁,当然可以通过按键D停止闪烁。

在键盘上先按F键,然后按D键,在从键盘键入想要设定的闹钟时间。

但时钟时间运行到设定的闹钟时间时,LED显示管连续闪烁30秒进行闹钟。

当然也可一通过按键D让其停止闪烁。

(二)心得体会:

时光飞逝,一转眼,一个学期又进尾声了,本学期的单片机课程设计也在一周内完成了。

俗话说“好的开始是成功的一半”。

说起课程设计,我认为最重要的就是做好设计的预习,认真的研究老师给的题目,选一个自己有兴趣的题目。

其次,要把老师上过的相关重点知识在温习一遍。

最后,要重视程序的模块化,修改的方便,也要注重程序的调试,掌握其方法。

虽然这次的课程设计算起来在实验室的时间只有四天,但在这四天学到了不少东西。

平时上课很多含糊的知识通过这次课程设计中有点明白了。

而且也能比较熟练的在实验平台上进行操作。

记得之前做实验时对操作平台胡乱操作,已经把设备连接好了,可重新运行时总是断开重连,断开重连,在这次课设中彻底改掉这个不好的习惯。

当然,由于我们没有上微机原理等基础课程,直接跨到单片机,基础很薄弱,在做的过程中遇到了不少困难。

最后在老师和同学的帮助下得以解决。

在这次难得的课程设计过程中我锻炼了自己的思考能力和动手能力。

通过这次课设,加强了我思考问题的完整性和实际生活联系的可行性。

再次感谢老师的辅导以及同学的帮助,是他们让我有了一个更好的认识,无论是学习还是生活,生活是实在的,要踏实走路。

课程设计时间虽然很短,但我学习了很多的东西,使我眼界打开,感受颇深。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3