振荡器分频器K1K2加1计数器溢出标记寄存器溢出中断请求信号T0或T1图2—12
定时/计数器的工作原理
2.振荡器
振荡器由单片机内部元件或内部元件与相应引脚所接的外部元件构成,产生一定频率(如8MHz)的系统时钟信号clkI/O。
3.分频器
Atmega8中由一个10位预定比例分频器构成,它将振荡器所产生的系统时钟信号按一定比例(如8或64)进行分频,形成符合计数器使用的计数时钟clkT。
4.T0或T1
T0或T1是来自单片机外部引脚T0或T1的时钟信号。 5.K1、K2
K1、K2是两个由定时/计数器控制寄存器TCCR控制的模拟开关。其中,K1控制加1计数器是对内部计数时钟计数(或计时)还是对外部时钟计数(或计时);K2控制加1计数器是否开始计数(或计时)。
6.加1计数器
加1计数器是定时/计数器的核心,它的基本功能就是对输入给它的脉冲进行计数。下面谈谈与加1计数器的有关的几个基本概念。
⑴ 计数器的容量
无论是计数还是定时,都不能无限地进行,应该有一个计数次数、定时时间长短的限制,否则单片机怎么知道计数已满、定时时间已到呢?那么单片机中的计数器有多大容量?对于8位计数器,它的最大计数容量是28=256;对于16位计数器,它的最大计数容量是216=65536。
⑵ 初值
计数器存在一个最大的计数范围、最长的定时时间。但在实际应用场合,往往不需要计数这么多次或定时这么长的时间。这里就涉及到计数器初值的问题。
比如一个空杯最多能装1000滴水,对了就溢出。但如果我想让它滴800滴水就溢出,怎么办呢?“乌鸦喝水”给我们很好的启示,只要在开始滴水之前就先往杯里放入200滴水。
对于计数器,其实也如此。比如说一个8位的计数器,最多能计256个脉冲。如果我想让它计156个脉冲就溢出,只要在计数开始之前在计数器中放入100个脉冲数就达到目的了。这个 100就是计数器的初值。
⑶ 溢出
既然计数器和我们日常使用的水杯一样,有一个最大容量的问题。因此,当计数器计数已满时,如果还继续往里面输入计数脉冲,那么它就会象一个水杯装满水后,如果继续往里面滴水,多余的水就会从水杯中流到地,这就是定时器的溢出。
日常生活中水杯的溢出和单片机中计数器的溢出,有相同的地方,也有不同之处。两者不同之处表现在:当水杯发生溢出现象时,只是使多余的水流到杯外,整个杯中装满了水,而计数器发生溢出时,不仅把多余的脉冲“流”到计数器外,而且会将计数器原来所计有的脉冲数全部清空;另外,水杯发生溢出后,不会自动再往杯中滴水,而计数器产生溢出后,它会自动从0开始计数。如果不想让它从0开始,那么可以对它重新赋初值,从所赋的初值开始计数。 二、Atmega8单片机定时/计数器
Atmega8单片机有3个定时/计数器:8位的定时/计数器0(T/C0)、16位的定时/计数器1(T/C1)、8位的定时/计数器2(T/C2)。这些定时/计数器除了能够实现通常的定时和计数功能外,还具有捕捉、比较、脉宽调制输出和实时时钟计数等功能。这里我们主要介绍它们的定时/计数功能。
㈠ 8位定时/计数器0——T/C0
定时/计数器0是一个单通道计数器,可以实现定时和对外部事件计数,它带有一个10位的预定比例分频器。下面我们看看与定时和计数有关的寄存器。
1.T/C0控制寄存器——TCCR0
位765432CS02R/W01CS01R/W00CS00R/W0TCCR0_R/WR复位值0_R0_R0_R0_R0
TCCR0主要通过不同的控制位来实现:①计数器的开始或停止;②对内部时钟计数(或定时),还是对外部时钟计数(或定时);③如果是对内部时钟计数(或定时),那么采用的预定分频比例是多少。具体定义如表2—12。
表2—12 T/C0时钟源选择 位2 位1 位0 说 明 0 0 0 无计数时钟源(定时/计数器停止) 0 0 1 采用系统时钟作为计数时钟源 0 1 0 采用系统时钟的8分频作为计数时钟源 0 1 1 采用系统时钟的64分频作为计数时钟源 1 0 0 采用系统时钟的256分频作为计数时钟源 1 0 1 采用系统时钟的1024分频作为计数时钟源 1 1 0 采用T0引脚输入的外部时钟(下降沿驱动) 1 1 1 采用T0引脚输入的外部时钟(上升沿驱动) 2.T/C0中断屏蔽寄存器——TIMSK 位76543210TOIE0TIMSKR/W0OCIE2TOIE2TICIE1OCIE1AOCIE1BTOIE1R/WR/WR/W0R/W0R/W0R/W0R/W0复位值0_R/W0
TIMSK主要功能之一就是控制T/C0溢出中断是开放还是屏蔽。当该寄存器的位0置“1”,且状态寄存器(SREG)的I位置“1”时,开放T/C0的溢出中断,否则,屏蔽T/C0的溢出中断。用C语言定义T/C0开放溢出中断的语句如下:
TIMSK=0X01;// T/C0溢出中断使能 SEI();//全局中断使能
3.T/C0溢出标志寄存器——TIFR
位7OCF26TOV2R/W05ICF1R/W04OCF1AR/W03OCF1BR/W02TOV1R/W010TOV0R/W0TIFR_R/W0R/WR/W复位值0
当T/C0产生溢出时,TIFR的位0变为“1”,向MCU提出溢出中断请求,
这是如果TIMSK的位0也置“1”(T/C0溢出中断使能),SREG的I位置“1”(全局中断使能),那么MCU转入T/C0溢出中断向量,执行中断服务程序,同时TIFR的位0自动清0,为下一次产生溢出中断作准备。写入一个逻辑“1”到TIFR的位0(如:TIFR=0X01),也可以将该位清0。
4.T/C0计数寄存器——TCNT0
TCNT0是一个8位寄存器,主要用于锁存T/C0计数器所记录的脉冲数。在用C编程时,主要利用TCNT0给计数器赋初值,如:TCNT0=0XB1;//给TCNT0赋初值B1。
㈡ 16位定时/计数器1——T/C1
定时/计数器1是一个真正的16位计数器,可以实现定时和对外部事件计数及捕捉、比较、脉宽调制输出的功能,它带有一个与T/C0相同的预定比例分频器。下面我们介绍它与定时和计数有关的寄存器。
1.T/C1控制寄存器A——TCCR1A
TCCRA是一个8位寄存器,其相应的位主要用于控制Atmega8比较输出引脚PB1、PB2的输出行为及波形发生器的工作模式等,有关这些内容我们在其它章节中介绍。
2.T/C1控制寄存器B——TCCR1B
位7654321CS11R/W00CS10TCCR1BR/W0ICNC1ICES1R/WR/WR/W0复位值0_R0WGM13WGM12CS12R/W0R/W0R/W0
TCCR0的位2、位1、位0的不同组合主要用来控制:①计数器的开始或停止;②对内部时钟计数(或定时),还是对外部时钟计数(或定时);③如果是对内部时钟计数(或定时),那么采用的预定分频比例是多少。具体定义如表2—13。
表2—13 T/C1时钟源选择
位2 位1 位0 说 明 0 0 0 无计数时钟源(定时/计数器停止) 0 0 1 采用系统时钟作为计数时钟源 0 1 0 采用系统时钟的8分频作为计数时钟源 0 1 1 采用系统时钟的64分频作为计数时钟源 1 0 0 采用系统时钟的256分频作为计数时钟源 1 0 1 采用系统时钟的1024分频作为计数时钟源 1 1 0 采用T1引脚输入的外部时钟(下降沿驱动) 1 1 1 采用T1引脚输入的外部时钟(上升沿驱动) 2.T/C1中断屏蔽寄存器——TIMSK 位76543210TOIE0TIMSKR/W0OCIE2TOIE2TICIE1OCIE1AOCIE1BTOIE1R/WR/WR/W0R/W0R/W0R/W0R/W0复位值0_R/W0
TIMSK主要功能之一就是控制T/C1溢出中断是开放还是屏蔽。当该寄存器的位0置“1”,且状态寄存器(SREG)的I位置“1”时,开放T/C1的溢出中断,否则,屏蔽T/C1的溢出中断。用C语言定义T/C1开放溢出中断的语句如下:
TIMSK=0X01;// T/C1溢出中断使能 SEI();//全局中断使能
3.T/C1溢出标志寄存器——TIFR
位7OCF2R/WR/W复位值06TOV2R/W05ICF1R/W04OCF1AR/W03OCF1BR/W02TOV1R/W010TOV0R/W0TIFR_R/W0
当T/C1产生溢出时,TIFR的位0变为“1”,向MCU提出溢出中断请求,
这是如果TIMSK的位0也置“1”(T/C1溢出中断使能),SREG的I位置“1”(全局中断使能),那么MCU转入T/C1溢出中断向量,执行中断服务程序,同时TIFR的位0自动清0,为下一次产生溢出中断作准备。写入一个逻辑“1”到TIFR的位0(如:TIFR=0X01),也可以将该位清0。
4.T/C1计数寄存器——TCNT1H和TCNT1L
TCNT0是一个16位寄存器,分为高8位计数寄存器TCNT1H和低8位计数寄存器TCNT1L,主要用于锁存T/C1计数器所记录的脉冲数。在用C编程时,主要利用它来给计数器赋初值,其中高8位赋给TCNT1H,低8位赋给TCNT1L如:
TCNT1H=0XFF;//给TCNT1H赋初值FF TCNT1L=0X62;//给TCNT1L赋初值62 ㈢ 8位定时/计数器2——T/C2
定时/计数器2是一个单通道计数器,可以实现对内部时钟定时和计数,而不能对外部事件进行计数,它带有一个与T/C0和T/C1不同的预定比例分频器。下面我们介绍与定时和计数有关的寄存器。
1.T/C2控制寄存器——TCCR2
位7FOC2R/W复位值W06WGM20R/W05COM21R/W04COM20R/W03WGM21R/W02CS22R/W01CS21R/W00CS20R/W0TCCR2
TCCR2主要通过位2、位1和位0的不同组合来实现:①计数器的开始或停止;②采用多大分频比例对内部时钟计数(或定时)。具体定义如表2—14。
表2—14 T/C2时钟源选择 位2 0 0 0 0 位1 0 0 1 1 位0 0 1 0 1 说 明 无计数时钟源(定时/计数器停止) 采用系统时钟作为计数时钟源 采用系统时钟的8分频作为计数时钟源 采用系统时钟的32分频作为计数时钟源 1 1 1 1 0 0 采用系统时钟的64分频作为计数时钟源 0 1 采用系统时钟的128分频作为计数时钟源 1 0 采用系统时钟的256分频作为计数时钟源 1 1 采用系统时钟的1024分频作为计数时钟源 2.T/C2中断屏蔽寄存器——TIMSK 位76543210TOIE0TIMSKR/W0OCIE2TOIE2TICIE1OCIE1AOCIE1BTOIE1R/WR/WR/W0R/W0R/W0R/W0R/W0_R/W0复位值0
TIMSK主要功能之一就是控制T/C2溢出中断是开放还是屏蔽。当该寄存器的位0置“1”,且状态寄存器(SREG)的I位置“1”时,开放T/C2的溢出中断,否则,屏蔽T/C2的溢出中断。用C语言定义T/C2开放溢出中断的语句如下:
TIMSK=0X01;// T/C2溢出中断使能 SEI();//全局中断使能
3.T/C2溢出标志寄存器——TIFR
位7OCF2R/W复位值R/W06TOV2R/W05ICF1R/W04OCF1AR/W03OCF1BR/W02TOV1R/W010TOV0R/W0TIFR_R/W0
当T/C2产生溢出时,TIFR的位6变为“1”,向MCU提出溢出中断请求,
这是如果TIMSK的位0也置“1”(T/C2溢出中断使能),SREG的I位置“1”(全局中断使能),那么MCU转入T/C2溢出中断向量,执行中断服务程序,同时TIFR的位6自动清0,为下一次产生溢出中断作准备。写入一个逻辑“1”到TIFR的位6(如:TIFR=0X40),也可以将该位清0。
4.T/C2计数寄存器——TCNT2
TCNT2是一个8位寄存器,主要用于锁存T/C2计数器所记录的脉冲数。在用C编程时,主要利用TCNT2给计数器赋初值,如:TCNT2=0XB1;//给TCNT2赋初值B1
三、定时/计数器应用C语言编程
㈠ 初始化
由于定时/计数器是可编程的,因此在任何一个定时/计数器开始工作之前,必须对其进行初始化。
1.初始化的步骤
①停止定时/计数器计数工作,即给TCCR0或TCCR1B、 TCCR2赋初值0X00。
②把定时、计数的初值写入TCNT0或TCNT1H、TCNT1L、 TCNT2计数寄存器中。
③通过定时/计数器控制寄存器TCCR0或TCCR1A、
TCCR1B、TCCR2设置该定时/计数器是对内部,还是外部时钟定时(或计数),以及所采用的分频比例,启动定时/计数器计数。
④如果采用溢出中断,还必须置位TIMSK寄存器的相应控 制位允许该定时/计数器溢出中断,同时开放全局中断。
2.注意事项