如何用TIMER0控制单只LED闪烁以示提醒

文库君已有近万本图书,还会不断收罗精品免费内容双手奉上,请及时续费哦!

两大类热门资源免费畅读

续费一年阅读会员,立省24元!

定时器是单片机的重要功能模块之一,在检测、控制领域有广泛应用。定时器常用作定时时钟,以实现定时检测,定时响应、定时控制,并且可以产生ms宽的脉冲信号,驱动步进电机。定时和计数的最终功能都是通过计数实现,若计数的事件源是周期固定的脉冲则可实现定时功能,否则只能实现计数功能。因此可以将定时和计数功能全由一个部件实现。通过下图可以简单分析定时器的结构与工作原理。

1、51单片机计数器的脉冲输入脚。主要的脉冲输入脚有Px,y, 也指对应T0的P3.4和对应T1的P3.5,主要用来检测片外来的脉冲。而引脚18和19则对应着晶振的输入脉冲,脉冲的频率和周期为

2、定时器有两种工作模式,分别为计数模式和定时模式。对Px,y的输入脉冲进行计数为计数模式。定时模式,则是对MCU的主时钟经过12分频后计数。因为主时钟是相对稳定的,所以可以通过计数值推算出计数所经过的时间。

4、TLx与THx之间的搭配关系

1)、TLx与THx之间32进制。即当TLx计到32个脉冲时,TLx归0同时THx进1。这也称为方式0。

3)、THx用于存放TLx溢出后,TLx下次计数的起点。这也称为方式2。

4)、THx与TLx分别独立对自己的输入脉冲计数。这也称为方式3。

1)、确定定时器的计数模式。

2)、确定TLx与THx之间的搭配关系。

3)、确定计数起点值。即TLx与THx的初值。

4)、是否开始计数。TRx

(1)和(2)可以由工作方式寄存器TMOD来设定,TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:


GATE:门控位,用于设置计数器计数与否,是否受P3.2或P3.3电压状态的影响。GATE=0时,表示计数器计数与否与两端口电压状态无关;GATA=1时,计数器是否计数要参考引脚的状态,即P3.2为高时T0才计数,P3.3为高时T1才计数。
M1M0:工作方式设置位。定时/计数器有四种工作方式,由M1M0进行设置。


计数器溢出后,THx与TLx都归0。并将特殊功能区中对应的溢出标志位TFx写为1。

好了,理论就讲述到这。现在我们通过一些实验来看看怎么使用定时器。

实验一、P1口连接的8个LED灯以1秒钟的频率闪烁。

上述代码的思路是每计算14个溢出,则翻转P1口状态。产生一个溢出的时间是71.1ms,14个则约为1s。

实验二、让一个LED灯每1秒钟闪烁。

相比于上个例子,这里有两个区别,首先是将timer0的溢出事件作为子函数单独出来,其次是注意翻转一个led灯时候用的是“!”。

例子三、让连接到P1口的LED1和LED8灯每1秒钟闪烁。

if(TF1==1) //软件查询,主循环每跑完一圈才会到这里。

相较于例二,例子三有几个点值得注意:

0x10,那么将造成LD1闪烁比LD8闪烁快8倍。分析一下,从main函数开始执行,先是初始化timer0,这时候定时器1设置为工作方式1。接着程序执行到Timer1_Init(),这时候TMOD=,即选定了timer1在工作方式1,但同时timer0重新配置为工作方式0, 也就是32进制,所以产生快8倍现象。

     那为什么用|这个符号就可以做到互不影响呢?|是或运算符,即有1出1,全0出0。什么意思呢?举个例子,a是,b是,那么a|b就是。通过引入这个符号,可以实现tmod对两个定时器的独立操作。

      首先解释下^这个符号。^称为异或运算符,相同出0,不同出1。举个例子,a是,b是,那么a^b就是。

(1<<i)是在将x的第i位翻转而同时不影响其他位。

上面三个例子实际都是采用了软件查询法。即main函数会每次进入到溢出事件函数里去判断TF0或1是否等于1,这样就浪费了大量CPU时间。同时,实时性差,假如在执行Timer0_Overflow()的时候timer1也溢出了,这时候timer1的溢出事件就没有及时处理。因此下面我们要引入中断系统。

中断系统是一套硬件电路,它可以在每个机器周期对所有的外设的标志位作查询。相比于前面的软件查询(if(xx==1)),中断系统也可以叫做硬件查询。51的中断系统可查询以下6个标志位。

IE0(TCON.1),外部中断0中断请求标志位。

IT1(TCON.2),外部中断1触发方式控制位。

IE1(TCON.3),外部中断1中断请求标志位。

TF0(TCON.5),定时/计数器T0溢出中断请求标志位。

RI(SCON.0)或TI(SCON.1),串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。 

当中断系统查询到外设的标志位变为1时,中断系统可暂停当前的主循环,并且将程序跳转到用户预先指定的函数中执行。要启动中断系统,必须先进行中断初始化,其流程如下:

a、是否要查询外设标志(EA=0或EA=1,EA 也叫 CPU中断允许(总允许)位)

b、查询到标志1,是否要跳程序

c、跳转的目标函数,即中断服务子函数

所以在使用定时器中断时,我们只需要首先初始化中断系统,开启总中断(相当于总开关),开启定时器对应的控制位(相当于支路开关),再初始化定时器即可。中断系统作为单片机的外设,只有在某个中断产生时才会打断主循环,并由相应的中断号引入到相应的中断服务子函数。下图是6个中断标志位的信息。

实验四、使用中断系统实现LD1灯每1秒钟闪烁。

//以下中断服务子程序,我们希望中断系统来调用,而不是我们在main函数里面调用,因此使用interrupt. */ //发现溢出后,中断系统根据中断号寻找中断子服务函数,并强行暂停主循环并进入子函数

显然使用中断系统查询得到的1s更为精确。因为中断系统独立于main函数运行。另外本程序还预装了timer0的初值,这样的话就可以实现比71ms更小的时间片,比如要求10ms就进入中断。关于初值的设定,请参考下图。


实验五、用定时器实现数码管显示1234。

//数码管的定时扫描,每5ms显示一个数码管,也就是说相同的数码管,每20ms会被重新装入同样的数值,根据人眼的延迟效应,人眼观测到的数码管上的数值是静态的。
 ET0=1; //TF0 如果这个标志为1,进入中断子函数
 
void load_smg() //将数码管显示缓冲区的数据,显示到数码管上
 
、实现按钮控制数码管上的数值加1或减1,并且当按住按钮不放时,能实现快速的增减。






这里的关键点在于如何实现快速增减,具体请详细分析代码。代码链接

制作非常精美,介绍十分详细,当然要加分. 51黑有你更精彩!!!

我要回帖

更多关于 led灯闪烁 的文章

 

随机推荐