资源描述
,基于AVR的单片嵌入式系统原理与实践应用
第8章 定时计数器的结构与应用
定时计数器(Timer/Counter)是单片机中最基本的接口之一,它的用途非常广泛,常用于计数、延时、测量周期、频率、脉宽、提供定时脉冲信号等。在实际应用中,对于转速,位移、速度、流量等物理量的测量,通常也是由传感器转换成脉冲电信号,通过使用定时计数器来测量其周期或频率,再经过计算处理获得。
相对于一般8位单片机而言,AVR不仅配备了更多的定时计数器接口,而且还是增强型的,如通过定时计数器与比较匹配寄存器相互配合,生成占空比可变的方波信号,即脉冲宽度调制输出PWM信号,用于D/A、马达无级调速控制、变频控制等,功能非常强大。
ATmega16一共配置了2个8位和1个16位,共3个定时计数器,它们是8位的定时计数器T/C0、T/C2和16位的定时计数器T/C1。本章将着重对AVR的8位定时计数器的结构、功能和应用进行讲解,并介绍基本的使用设计方法。
8.1 定时计数器的结构
在单片机内部,一般都会集成由专门硬件电路构成的可编程定时计数器。定时计数器最基本的功能就是对脉冲信号“自动”进行计数。这里所谓的“自动”,指计数的过程是由硬件完成的,不需要MCU的干预。但MCU可以通过指令设置定时计数器的工作方式,以及根据定时计数器的计数值或工作状态做必要的处理和响应。
学习和使用定时计数器时,必须注意以下的基本要素:
ü 定时计数器的长度。定时计数器的长度是指计数单元的位长度,一般为8位(一个字节)或16位(2个字节)。
ü 脉冲信号源。脉冲信号源是指输入到定时计数器的计数脉冲信号。通常用于定时计数器计数的脉冲信号可以由外部输入引脚提供,也可以由单片机内部提供。
ü 计数器类型。计数器类型是指计数器的计数运行方式,可分为加一(减一)计数器,单程计数或双向计数等。
ü 计数器的上下限。计数器的上下限指计数单元的最小值和最大值。一般情况下,计数器的下限值为零,上限值为计数单元的最大计数值,即255(8位)或65535(16位)。需要注意的是,当计数器工作在不同模式下时,计数器的上限值并不都是计数单元的最大计数值255或65535,它将取决于用户的配置和设定。
ü 计数器的事件。计数器的事件指计数器处于某种状态时的输出信号,该信号通常可以向MCU申请中断。如当计数器计数到达计数上限值255时,产生“溢出”信号,向MCU申请中断。
8.1.1 8位定时计数器T/C0的结构
ATmega16中有两个8位的定时计数器:T/C0、T/C2,它们都是通用的多功能定时计数器,其主要特点是:
ü 单通道计数器。
ü 比较匹配时清零计数器(自动重装特性,Auto Reload)。
ü 可产生无输出抖动(glitch-free)的,相位可调的脉宽调制(PWM)信号输出。
ü 频率发生器。
ü 外部事件计数器(仅T/C0)。
ü 带10位的时钟预分频器。
ü 溢出和比较匹配中断源(TOV0、OCF0和TOV2、OCF2)。
ü 允许使用外部引脚的32kHz手表晶振作为独立的计数时钟源(仅T/C2)。
T/C0、T/C2的主要结构和大部分的功能是相同或类似的,因此,我们先介绍T/C0的结构和应用。
1.T/C0的组成结构
图8-1为8位T/C0的硬件结构框图。图中给出了MCU可以操作的寄存器以及相关的标志位。在T/C0中,有两个8位的寄存器:计数寄存器TCNT0和输出比较寄存器OCR0。其它相关的寄存器还有T/C0的控制寄存器TCCR0,中断标志寄存器TIFR和定时器中断屏蔽寄存器TIMSK。T/C0的计数器事件输出信号有两个,计数器计数溢出TOV0和比较匹配相等OCF0。这两个事件的输出信号都可以申请中断,中断请求信号TOV0、OCF0可以在定时器中断标志寄存器TIFR中找到,同时在定时器中断屏蔽寄存器TIMSK中,可以找到与TOV0、OCF0对应的两个相互独立的中断屏蔽控制位TOIE0、OCIE0。
图8-1 8位T/C0的结构框图
(1)T/C0的时钟源
T/C0的计数时钟源可由来自外部引脚T0的信号提供,也可来自芯片的内部。图8-2为T/C0时钟源部分的内部功能图。
l T/C0计数时钟源的选择
T/C0的时钟源的选择由T/C0的控制寄存器TCCR0中的3个标志位CS0[2:0]确定,共有8种选择。其中包括无时钟源(停止计数),外部引脚T0的上升沿或下降沿,以及内部系统时钟经过一个10位预定比例分频器分频的5种频率的时钟信号(1/1、1/8、1/64、1/256、1/1024)。T/C0与T/C1共享一个预定比例分频器,但它们时钟源的选择是独立的。
l 使用系统内部时钟源
当定时计数器使用系统内部时钟作为计数源时,通常作为定时器和波形发生器使用。因为系统时钟的频率是已知的,这样通过计数器的计数值就可以知道时间值。
AVR在定时计数器和内部系统时钟之间增加了一个预定比例分频器,分频器对系统时钟信号进行不同比例的分频,分频后的时钟信号提供定时计数器使用。利用预定比例分频器,定时计数器可以从内部系统时钟获得几种不同频率的计数脉冲信号,使用非常灵活。
图8-2 T/C0的时钟源与10位预定比例分频器
l 使用外部时钟源
当定时计数器使用外部时钟作为计数源时,通常作为计数器使用,用于记录外部脉冲的个数。图8-3为外部时钟源的检测采样逻辑功能图。
图8-3 T/C0外部时钟检测采样逻辑功能图
外部引脚T0(PB0)上的脉冲信号可以作为C/T0的计数时钟源。PB0引脚内部有一个同步采样电路(Synchronization),它在每个系统时钟周期都对T0引脚上的电平进行同步采样,然后将同步采样信号送到边沿检测器(Edge Detector)中。同步采样电路在系统时钟的上升沿将引脚信号电平打入寄存器,因此当系统的时钟频率大大高于外部引脚上电平变化的频率时,同步采样寄存器可以看作是透明的。边沿检测电路对同步采样的输出信号进行边沿检测,当检测到一个正跳变(CS0[2:0]=7)或负跳变(CS0[2:0]=8)时产生一个计数脉冲CLKT0。
由于引脚内部的同步采样和边沿检测电路的存在,引脚电平的变化需要经过2.5~3.5个系统时钟后才能在边沿检测的输出端上反映出来。因此,要使外部时钟源能正确的被引脚的检测采样,外部时钟源的最高频率不能大于 fclk_I/O/2.5,脉冲宽度也要大于一个系统时钟周期。另外,外部时钟源是不进入预定比例分频器进行分频的。
(2)T/C0的计数单元
T/C0的计数单元是一个可编程的8位双向计数器,图8-4是它的逻辑功能图,图中符号所代表的意义如下:
l 计数(count) TCNT0加1或减1。
l 方向(direction) 加或减的控制。
l 清除(clear) 清零TCNT0。
l 计数时钟(clkT0) C/T0时钟源
l 顶部值(TOP) 表示TCNT0计数值到达上边界。
l 底部值(BOTTOM) 表示TCNT0计数值到达下边界(零)。
图8-4 T/C0计数单元逻辑功能图
T/C0根据计数器的工作模式,在每一个clkT0时钟到来时,计数器进行加1、减1或清零操作。clkT0的来源由标志位CS0[2:0]设定。当CS0[2:0]=0时,计数器停止计数(无计数时钟源)。
T/C0的计数值保存在8位的寄存器TCNT0中,MCU可以在任何时间访问(读/写)TCNT0。MCU写入TCNT0的值将立即覆盖其中原有的内容,同时也会影响到计数器的运行。
计数器的计数序列取决于寄存器TCCR0中标志位WGM0[1:0]的设置。WGM0[1:0]的设置直接影响到计数器的计数方式和OC0的输出,同时也影响和涉及T/C0的溢出标志位TOV0的置位。标志位TOV0可以用于产生中断申请。
(3)比较匹配单元
图8-5 T/C0比较匹配单元逻辑功能图
图8-5为T/C0的比较匹配单元逻辑功能图。在T/C0运行期间,比较匹配单元一直将寄存器TCNT0的计数值同寄存器OCR0的内容进行比较(硬件进行自动比较处理)。一旦两者相等,在下一个计数时钟脉冲到达时置位OCF0标志位。标志位OCF0也可以用于产生中断申请。根据WGM0[1:0]和COM0[1:0]的不同设置,可以控制比较匹配单元产生和输出不同类型的脉冲波形。
寄存器OCR0实际上配置有一个辅助缓存器。当T/C0工作在非PWM模式下时,该辅助缓存器处于被禁止使用状态,此时MCU直接访问和操作寄存器OCR0。当T/C0工作在PWM模式时,该辅助缓存器投入使用,这时MCU对OCR0的访问操作,实际上是对OCR0的辅助缓存器操作。一旦计数器TCNT0的计数值达到设定的最大值(TOP)或最小值(BOTTOM)时,辅助缓存器中的内容将同步更新比较寄存器OCR0的值。这将有效防止产生奇边非对称的PWM脉冲信号,使输出的PWM波中没有杂散脉冲。
l 强制输出比较
在非PWM波形发生模式下,写1到强制输出比较位(FOC0)时,将强制比较器产生一个比较匹配输出信号。强制比较输出信号不会置OCF0标志位或重新装载/清零计数器,但是会像真的发生了比较匹配事件一样更新OC0输出引脚输出。
l 通过写TCNT0寄存器屏蔽比较匹配事件
任何MCU对TCNT0寄存器的写操作都会屏蔽在下一个定时器时钟周期中的发生的比较匹配事件,即使在定时器暂停时。这一特性使OCR0可以被初始化为与TCNT0相同的值,而不会在定时计数器被使能时触发中断。
l 使用输出比较单元
由于在任何工作模式下,写TCNT0寄存器都会使得输出比较匹配事件被屏蔽一个定时器时钟周期,因此可能会影响比较匹配输出的正确性。例如,写入一个与OCR0相同的值到TCNT0时,将丢失一次比较匹配事件,从而引起发生不正确的波形。同样,当定时器是向下计数时,不要将下边界的值写入TCNT0。
外部引脚OC0的设置必须在设置该端口引脚(PB3)为输出之前。设置OC0的值最简单的方法是在通常模式下使用FOC0来设置,这是因为在改变工作模式时,OC0寄存器将保持其原来的值。
需要注意的是,COM0[1:0]是无缓冲的,改变COM0[1:0]位的设置,会立即影响T/C0的工作方式。
(4)比较匹配输出单元
标志位COM0[1:0]有两个作用:定义OC0的输出状态,以及控制外部引脚OC0是否输出OC0寄存器的值。图8-6为比较匹配输出单元的逻辑图。
图8-6 T/C0比较匹配输出单元逻辑图
当标志位COM0[1:0]中任何一位为“1”时,波形发生器的输出OC0取代引脚PB3原来的I/O功能,但引脚的方向寄存器DDRB3仍然控制OC0引脚的输入/输出方向。如果要在外部引脚PB3上输出OC0的逻辑电平,应设定DDRB3定义该引脚为输出脚。采用这种结构,用户可以先初始化OC0的状态,然后再允许其由引脚PB3输出。
(5)比较输出模式和波形发生器
T/C0有四种工作模式,根据COM0[1:0]的不同设定,波形发生器将产生各种不同的脉冲波形,如PWM波形的产生和输出。但只要COM0[1:0]=0,波形发生器对OC0寄存器没有任何作用。
2.与8位T/C0相关的寄存器
(1)T/C0计数寄存器—TCNT0
位
7
6
5
4
3
2
1
0
$32($0052)
TCNT0
读/写
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
初始化值
0
0
0
0
0
0
0
0
TCNT0是T/C0的计数值寄存器,该寄存器可以直接被MCU读写访问。写TCNT0寄存器将在下一个定时器时钟周期中阻塞比较匹配。因此,在计数器运行期间修改TCNT0的内容,有可能将丢失一次TCNT0与OCR0的匹配比较操作。
(2)输出比较寄存器—OCR0
位
7
6
5
4
3
2
1
0
$3C($005C)
OCR0
读/写
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
初始化值
0
0
0
0
0
0
0
0
8位寄存器OCR0中的数据用于同TCNT0寄存器中的计数值进行匹配比较。在T/C0运行期间,比较匹配单元一直将寄存器TCNT0的计数值同寄存器OCR0的内容进行比较。一旦TCNT0的计数值与OCR0的数据匹配相等,将产生一个输出比较匹配相等的中断申请,或改变OC2的输出逻辑电平。
(3)定时计数器中断屏蔽寄存器—TIMSK
位
7
6
5
4
3
2
1
0
$39($0059)
OCIE2
TOIE2
TICIE1
OCIE1A
OCIE1B
TOIE1
OCIE0
TOIE0
TIMSK
读/写
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
初始化值
0
0
0
0
0
0
0
0
l 位7(位1)— OCIE2(OCIE0):T/C2(T/C0)输出比较匹配中断允许标志位
当OCIE2(OCIE0)被设为“1”,且状态寄存器中的I位被设为“1”时,将使能T/C2(T/C0)的输出比较匹配中断。若在T/C2(T/C0)上发生输出比较匹配,即OCF2=1(OCF0=1)时,则执行T/C2(T/C0)输出比较匹配中断服务程序。
l 位6(位0)— TOIE2(TOIE0):T/C2(T/C0)溢出中断允许标志位
当TOIE2(TOIE0)被设为“1”,且状态寄存器中的I位被设为“1”时,将使能T/C2(T/C0)溢出中断。若在T/C2(T/C0)上发生溢出,即TOV2=1(TOV0=1)时,则执行T/C2(T/C0)溢出中断服务程序。
(4)定时计数器中断标志寄存器—TIFR
位
7
6
5
4
3
2
1
0
$38($0058)
OCF2
TOV2
ICF1
OCF1A
OCF1B
TOV1
OCF0
TOV0
TIFR
读/写
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
初始化值
0
0
0
0
0
0
0
0
l 位7(位1)— OCF2(OCF0):T/C2(T/C0)比较匹配输出的中断标志位
当T/C2(T/C0)输出比较匹配成功,即TCNT2=OCR2(TCNT0=OCR0)时,OCF2(OCF0)位被设为“1”。当转入T/C2(T/C0)输出比较匹配中断向量执行中断处理程序时,OCF2(OCF0)由硬件自动清零。写入一个逻辑“1”到OCF2(OCF0)标志位将清除该标志位。当寄存器SREG中的I位、OCIE2(OCIE0)以及OCF2(OCF0)均为“1”时,T/C2(T/C0)的输出比较匹配中断被执行。
l 位6(位0)— TOV2(TOV0):T/C2(T/C0)溢出中断标志位
当T/C2(T/C0)产生溢出时,TOV2(TOV0)位被设为“1”。当转入T/C2(T/C0)溢出中断向量执行中断处理程序时,TOV2(TOV0)由硬件自动清零。写入一个逻辑“1”到TOV2(TOV0)标志位将清除该标志位。当寄存器SREG中的I位、TOIE2(TOIE0)以及TOV2(TOV0)均为“1”时,T/C2(T/C0)的溢出中断被执行。在PWM模式中,当T/C2(T/C0)计数器的值为0x00并改变计数方向时,TOV2(TOV0)自动被置为“1”。
(5)T/C0控制寄存器—TCCR0
位
7
6
5
4
3
2
1
0
$33($0053)
FOC0
WGM00
COM01
COM00
WGM01
CS02
CS01
CS00
TCCR0
读/写
R/W
R/W
R/W
R/W
R/W
R/W
R/W
R/W
初始化值
0
0
0
0
0
0
0
0
8位寄存器TCCR0是T/C0的控制寄存器,它用于选择计数器的计数源,工作模式和比较输出的方式等。
l 位7—FOC0:强制输出比较
FOC0位只在T/C0被设置为非PWM模式下工作时才有效,但为了保证同以后的器件兼容,在PWM模式下写TCCR0寄存器时,该位必须被写零。当将一个逻辑“1”写到FOC0位时,会强加在波形发生器上一个比较匹配成功信号,使波形发生器依据COM0[1:0]位的设置而改变OC0输出状态。注意:FOC0的作用仅如同一个选通脉冲,而OC0的输出还是取决于COM0[1:0]位的设置。
一个FOC0选通脉冲不会产生任何的中断申请,也不影响计数器TCNT0和寄存器OCR0的值。一旦一个真正的比较匹配发生,OC0的输出将根据COM0[1:0]位的设置而更新。
l 位3,6—WGM0[1:0]:波形发生模式
这两个标志位控制T/C0的计数和工作方式,计数器计数的上限值,以及确定波形发生器的工作模式(见表8.1)。T/C0支持的工作模式有:普通模式,比较匹配时定时器清零(CTC)模式,以及两种脉宽调制(PWM)模式。
表8.1 T/C0的波形产生模式
模 式
WGM01
WGM00
T/C0工作模式
计数上限值
OCR0更新
TOV0置位
0
0
0
普通模式
0xFF
立即
0xFF
1
0
1
PWM,相位可调
0xFF
0xFF
0x00
2
1
0
CTC模式
OCR0
立即
0xFF
3
1
1
快速PWM
0xFF
0xFF
0xFF
l 位5,4—COM0[1:0]:比较匹配输出方式
这两个位用于控制比较输出引脚OC0的输出方式。如果COM0[1:0]中的任何一位或两位被置“1”,OC0的输出将覆盖PB3引脚的通用I/O端口功能,但此时PB3引脚的数据方向寄存器DDRB3位必须置为输出方式。当引脚PB3作为OC0输出引脚时,其输出方式取决于COM0[1:0]和WGM0[1:0]的设定。
表8.2给出了在WGM0[1:0]的设置为普通模式和CTC模式(非PWM)时,COM0[1:0]位的功能定义。表8.3给出了在WGM0[1:0]的设置为快速PWM模式时,COM0[1:0]位的功能定义。表8.4给出了在WGM0[1:0]设置为相位可调的PWM模式时,COM0[1:0]位的功能定义。
表8.2 比较输出模式,非PWM模式(WGM = 0、2)
COM01
COM00
说 明
0
0
PB3为通用I/O引脚(OC0与引脚不连接)
0
1
比较匹配时触发OC0(OC0为原OC0的取反)
1
0
比较匹配时清零OC0
1
1
比较匹配时置位OC0
表8.3 比较输出模式,快速PWM模式(WGM = 3)
COM01
COM00
说 明
0
0
PB3为通用I/O引脚(OC0与引脚不连接)
0
1
保留
1
0
比较匹配时清零OC0,计数值为0xFF时置位OC0
1
1
比较匹配时置位OC0,计数值为0xFF时清零OC0
表8.4 比较输出模式,相位可调PWM模式(WGM = 1)
COM01
COM00
说 明
0
0
PB3为通用I/O引脚(OC0与引脚不连接)
0
1
保留
1
0
向上计数过程中比较匹配时清零OC0
向下计数过程中比较匹配时置位OC0
1
1
向上计数过程中比较匹配时置位OC0
向下计数过程中比较匹配时清零OC0
l 位2,0—CS0[2:0]:T/C0时钟源选择
这3个标志位被用于选择设定T/C0的时钟源,见表8.5。
表8.5 T/C0的时钟源选择
CS02
CS01
CS00
说 明
0
0
0
无时钟源(停止T/C0)
0
0
1
clkT0S(不经过分频器)
0
1
0
clkT0S/8(来自预分频器)
0
1
1
clkT0S/64(来自预分频器)
1
0
0
clkT0S/256(来自预分频器)
1
0
1
clkT0S/1024(来自预分频器)
1
1
0
外部T0脚,下降沿驱动
1
1
1
外部T0脚,上升沿驱动
8.1.2 8位T/C0的工作模式
T/C0的控制寄存器TCCR0的标志位WGM0[1:0]和COM0[1:0]的组合构成T/C0的四种工作模式以及OC0不同方式的输出。
(1)普通模式(WGM0[1:0]=0)
普通模式是T/C0最简单和基本的一种工作方式。T/C0工作在普通模式下时,计数器为单向加1计数器,一旦寄存器TCNT0的值到达0xFF(上限值),在下一个计数脉冲到来时便恢复为0x00,并继续单向加1计数。当TCNT0由0xFF转变为0x00的同时,溢出标志位TOV0置位为“1”,用于申请T/C0溢出中断。一旦MCU响应T/C0的溢出中断,硬件则将自动把TOV0清零。
考虑到T/CO在正常的计数过程中,当TCNTO值由0xFF返回0x00时能将标志位TOV0置“1”(注意:不能清零),而且当MCU响应T/C0的溢出中断时,硬件会自动把TOV0清零。因此溢出标志位TOV0也可作为计数器的第9位使用,使T/C0变成9位的计数器。但这种提高定时器的分辨率的方法,需要通过软件配合实现。
与其它工作模式相比,T/C0工作在普通模式时,不会产生任何其它的特殊状态,用户可以随时改变计数器TCNT0的数值。
在普通模式中,同样可以使用比较匹配功能产生定时中断,但最好不要在普通模式下使用输出比较单元来产生PWM波形输出,因为这将占用过多的MCU的时间。
(2)比较匹配清零计数器CTC模式(WGM2[1:0]=2)
T/C0工作在CTC模式下时,计数器为单向加1计数器,一旦寄存器TCNT0的值与OCR0的设定值相等(此时寄存器OCR0的值为计数上限值),就将计数器TCNT0清零为0x00,然后继续向上加1计数。通过设置OCR0的值,可以方便地控制比较匹配输出的频率,也方便了外部事件计数的应用。图8-7为CTC模式的计数时序图。
图8-7 T/C0的CTC模式计数时序
在TCNT0与OCR0匹配的同时,置比较匹配标志位OCF0为“1”。标志位OCF0可以用于申请中断。一旦MCU响应比较匹配中断,用户在中断服务程序中可以修改OCR0的值。
修改OCR0的值时需要注意,当T/C0的计数时钟频率比较高时,如果写入OCR0的值与0x00接近,可能会丢失一次比较匹配成立条件。例如:当TCNT0的值与OCR0匹配相等,此时TCNT0被硬件清零并申请中断;在中断服务中重新改变设置OCR0为0x05;但中断返回后TCNT0的计数值已经为0x10了,因此便丢失了一次比较匹配成立条件。此时计数器将继续加1计数到0xFF,然后返回0x00,当再次计数到0x05时,才能产生比较匹配成功。
在CTC模式下利用比较匹配输出单元产生波形输出时,应设置OC0的输出方式为触发方式(COM0[1:0]=1)。OC0输出波形的最高频率为fOC0=fclk_I/O/2(OCR0=0x00)。其他的频率输出由下式确定,式中N的取值为1、8、64、256或1024。
除此之外,与普通模式相同,当TCNT0计数值由0xFF转到0x00时,标志位TOV0置位。
(3)快速PWM模式(WGM0[1:0]=3)
T/C0工作在快速PWM模式可以产生较高频率的PWM波形。当T/C0工作在此模式下时,计数器为单程向上的加1计数器,从0x00一直加到0xFF(上限值),在下一个计数脉冲到来时便恢复为0x00,然后再从0x00开始加1计数。在设置正向比较匹配输出(COM0[1:0]=2)方式中,当TCNT0的计数值与OCR0的值相同匹配时清零OC0,当计数器的值由0xFF返回0x00时置位OC0。而在设置反向比较匹配输出(COM0[1:0]=3)方式中,当TCNT0的计数值与OCR0的值相同匹配时置位OC0,当计数器的值由0xFF返回0x00时清零OC0。图8-8为快速PWM工作时序图。
图8-8 T/C0快速PWM工作时序
由于快速PWM模式采用单程计数方式,所以它可以产生比相位可调PWM模式高一倍频率的PWM波。因此快速PWM模式适用于电源调整、DAC等应用。
在TCNT0的计数值到达0xFF时,置溢出标志位TOV0为“1”。标志位TOV0可以用于申请中断。一旦MCU响应TOV0中断,用户可以在中断服务程序中修改OCR0的值。
OC0输出的PWM波形的频率输出由下式确定,式中N的取值为 1、8、64、256或1024。
通过设置寄存器OCR0的值,可以获得不同占空比的脉冲波形。OCR0的一些特殊值,会产生极端的PWM波形。当OCR0的设置值为0x00时,会产生周期为MAX+1的窄脉冲序列。而设置OCR0的值为0xFF时,OC0的输出为恒定的高(低)电平。
当OC0的输出方式为触发方式时(COM0[1:0]=1),T/C0将产生占空比为50%的PWM波形。此时设置OCR0的值为0x00时,T/C0将产生占空比为50%的最高频率PWM波形,频率为fOC0=fclk_I/O/2。
(4)相位可调PWM模式(WGM0[1:0]=1)
相位可调PWM模式可以产生高精度相位可调的PWM波形。当T/C0工作在此模式下时,计数器为双程计数器:从0x00一直加到0xFF,在下一个计数脉冲到达时,改变计数方向,从0xFF开始减1计数到0x00。设置正向比较匹配输出(COM0[1:0]=2)方式:在正向加1过程中,TCNT0的计数值与OCR0的值相同匹配时清零OC0;在反向减1过程中,当计数器TCNT0的值与OCR0相同时置位OC0。设置反向比较匹配输出(COM0[1:0]=3)方式:在正向加1过程中,TCNT0的计数值与OCR0的值相同匹配时置位OC0;在反向减1过程中,当计数器TCNT0的值与OCR0相同时清零OC0。图8-9为相位可调PWM工作时序图。
图8-9 T/C0相位可调PWM工作时序
由于相位可调PWM模式采用双程计数方式,所以它产生的PWM波的频率比快速PWM低。其相位可调的特性(即OC0逻辑电平的改变不是固定在TCNT0=0x00处),适用于马达控制一类的应用。
在TCNT0的计数值到达0x00时,置溢出标志位TOV0为“1”。标志位TOV0可以用于申请溢出中断。
在相位可调PWM模式下,OC0输出的PWM波形频率由下式确定,式中N的取值为 1、8、64、256或1024。
通过设置寄存器OCR0的值,可以获得不同占空比的脉冲波形。OCR0的一些特殊值,会产生极端的PWM波形。当COM0[1:0]=2且OCR0的值为0xFF时,OC0的输出为恒定的高电平;而OCR0的值为0x00时,OC0的输出为恒定的低电平。
8.1.3 8位T/C0的计数工作时序
图8-10、图8-11、图8-12和图8-13给出了T/C0在同步工作情况下的各种计数时序,同时给出标志位TOV0和OCF0的置位条件。图中MAX=0xFF,BOTTOM=0x00,TOP=[OCRn]。
图8-10 T/C0计数时序(无预分频)
图8-10是T/C0对外部时钟或直接对内部时钟(无分频)计数工作的时序图。从图中看出,T/C0的计数是同系统时钟同步的(在系统时钟上升沿)。当TCNT0的值到达MAX(0xFF)后,在下一个系统时钟的上升沿处把TCNT0的值清为BOTTOM(0x00),同时置位TOV0申请中断。然而T/C0的计数过程并没有停止,重新从0x00开始继续加1计数。
图8-11 T/C0计数时序,带1/8预分频
图8-11是T/C0对经过预分频器的内部时钟(8分频)计数工作的时序图。从图中看出,T/C0的计数是同系统时钟同步的(每隔8个系统时钟的上升沿)。当TCNT0的值到达MAX(0xFF)后,在接下来第8个系统时钟的上升沿处将TCNT0的值清为BOTTOM(0x00),同时置位TOV0申请中断。然而T/C0的计数过程并没有停止,重新从0x00开始继续加1计数。
图8-12 T/C0计数时序,OCFn置位,带1/8预分频(CTC模式除外)
图8-12给出了T/C0工作在各种模式(除CTC模式外)时,比较匹配输出的标志位OCF0的置位情况。在T/CO对经过预分频器的内部时钟(8分频)计数过程中,比较匹配单元将寄存器TCNT0中的计数值和比较匹配寄存器OCR0中的值进行比较。一旦两者相等,在下一个计数脉冲到达时置位OCF0标志位,申请中断,然而T/C0的计数过程并没有停止,继续加1向上计数。
图8-13是T/C0工作在CTC模式时的比较匹配输出标志位OCF0的置位情况。在T/CO对经过预分频器的内部时钟(8分频)计数过程中,比较匹配单元将寄存器TCNT0中的计数值和比较匹配寄存器OCR0中的值进行比较。一旦两者相等(此时OCR0的值是计数器的上限值TOP),在下一个计数脉冲到达时置位OCF0标志位,申请中断,并同时将TCNT0的值清为BOTTOM(0x00)。然而T/C0的计数过程并没有停止,重新从0x00开始继续加1计数。
图8-13 T/C0计数时序,OCFn置位,带1/8预分频(CTC模式)
8.2 8位定时计数器T/C0的应用
使用定时计数器进行系统设计是非常灵活的,用户需要对实际的情况做仔细的分析,充分考虑利用定时计数器的特点,采用不同的方式来实现。
尽管定时计数器的基本工作原理比较简单,其基本特点为:
ü 对一个序列的脉冲信号进行计数,而且计数过程由硬件自己完成,不需要软件干预。
ü 一旦计数值到达某个值,通常是MAX(0xFF)、BOTTOM(0x00)或TOP时,可以产生中断申请,通知MCU进行处理。
但在实际使用中,如果能巧妙的结合定时计数器各种不同的工作模式,则会产生多种变化。因此用户在使用定时计数器进行设计时,应该注意以下几个要点。
ü 仔细确定使用哪个定时计数器。ATmega16一共配置了2个8位和1个16位,共3个定时计数器,不仅长度不同,而且其功能也不同。要选择适合的定时计数器使用。
ü 脉冲信号源。脉冲信号源是指输入到定时计数器的计数脉冲信号。用于定时计数器计数的脉冲信号可以由外部输入引脚提供,也可以由单片机内部提供。当使用内部计数脉冲信号时,应选择合适的分频比例与计数值的配合(建议使用CVAVR系统中的程序生成器功能)。
ü 计数器的工作模式和触发方式的选择。
ü 中断服务程序的正确设计。定时计数器的使用通常都是与中断相结合一起使用的,因此要非常清楚中断的产生条件,以及在中断服务程序中正确的进行中断处理以及相关的设置。
本节将给出一些定时计数器基本的应用和设计,以便读者能在学习和理解这些基本使用方法的过程中,更好的掌握定时计数器的特点,进而能达到能真正的在实际系统中灵活的使用定时计数器的目的。
8.2.1 外部事件计数器
注意,外部引脚T0输入的脉冲信号是不通过ATmega16内部的预分频器的。
T/C0作为外部事件计数器使用时,是指其计数脉冲信号来自外部的引脚T0(PB0)。
通常对外部输入的脉冲信号的基本处理有两种:
ü 对外部的脉冲信号进行计数,即记录脉冲的个数,一旦记录的脉冲个数到达一设定值时进行必要的处理。
ü 对外部的脉冲信号的频率(周期)进行测定。
在本小节中,我们只介绍前一种的应用。关于对外部的脉冲信号的频率(周期)进行测定的设计,将在本书后面的相关章节中介绍。
例8.1 2N分频系统设计一
1) 硬件电路
2N分频系统要实现的功能是对TO脚输入的方波信号进行偶数次的分频,以获得频率低于TO输入的方波信号。
本设计的硬件电路非常简单,将实验板上的250Hz的方波信号输出与ATmega16的T0脚连接,作为T/C0计数器的外部输入。另外将PA0作为分频后的脉冲输出脚,用PAO控制一个LED的显示,通过LED的亮暗变化可以简单的观察方波的频率。当然最好的方式是使用示波器观察PA0的输出。
2) 软件设计
首先考虑使用T/C0的普通模式(WGM0[1:0]=0),采用TO上升沿触发(CS0[2:0]=111),并设置TCNT0的初值为0xFF。当TO引脚输入电平出现一个上跳变时,T/CO的TCNTO回到0x00,并产生溢出中断(参考图8-10),在溢出中断服务中重新设置TCNT0为0xFF,并改变PA0口的输出电平(取反输出)。在TO引脚输入电平出现第二个上跳变时,又会产生中断,在中断服务程序中再次改变PAO的输出,这样在PAO上就得到TO的2分频输出信号。同理,如果将TCNT0的初值设置为0xFE,则在PA0上得到TO的4分频输出信号,0xFDà6分频,0xFC—>8分频……,而当TCNT0的初值设置为0x00时,可实现最大512分频的输出。
下面,我们给出在PA0上输出1Hz的方波(LED亮0.5s,暗0.5s)的设计和程序。由于T0输入的频率为250Hz,所以分频系数为250,因此TCNTO的初值=255-124(0x83),即T/C0计数125次时PA0的电平改变一次。
再次建议读者使用CVAVR中的程序生成向导功能来帮助你建立整个程序的框架,以及芯片的初始化部分的语句,可以省掉你过多的查看器件手册和考虑寄存器的设置值等。
图8-14是在CVAVR的程序生成向导中设置T/C0的对话窗口。选择T/CO的计数时钟源为T0的上升沿,工作方式为普通模式,允许溢出中断,TCNT0的初值为0x83。
利用CVAVR的程序生成向导,在它的帮助下生成一个程序框架后,然后再加入自己的程序和进行必要的修改。
图8-14 在程序生成向导中设置T/C0
/*********************************************
File name : Demo_8_1.c
Chip type : ATmega16
Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*********************************************/
#include <mega16.h>
// Timer 0 溢出中断服务
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x83; // 重新设置TCNT0的初值
PORTA.0 = ~PORTA.0; // PA0取反输出
}
void main(void)
{
PORTA=0x01;
DDRA=0x01; // 设置PA0输出方式
PORTB=0x01;
DDRB=0x00; // 设置PB0(T0)为输入方式
// T/C0 初始化
TCCR0=0x07; // T/C0工作于普通模式,T0上升沿触发
TCNT0=0x83;
OCR0=0x00;
TIMSK=0x01; // 允许T0溢出中断
#asm("sei") // 开放全局中断
展开阅读全文