,基于AVR的单片嵌入式系统原理与实践应用
设置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。
fOC0PCPWM?fclk_I/O 510N通过设置寄存器OCR0的值,可以获得不同占空比的脉冲波形。OCR0的一些特殊值,会产生极端的PWM波形。当COM0[1:0]=2且OCR0的值为0xFF时,OC0的输出为恒定的高电平;而OCR0的值为0x00时,OC0的输出为恒定的低电平。
华东师范大学 电子系 马 潮 8-11
第8章 8位定时计数器结构与应用
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模式除外)
,基于AVR的单片嵌入式系统原理与实践应用
图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-13
第8章 8位定时计数器结构与应用
本节将给出一些定时计数器基本的应用和设计,以便读者能在学习和理解这些基本使用方法的过程中,更好的掌握定时计数器的特点,进而能达到能真正的在实际系统中灵活的使用定时计数器的目的。
8.2.1 外部事件计数器
T/C0作为外部事件计数器使用时,是指其计数脉冲信号来自外部的引脚T0(PB0)。
注意,外部引脚T0输入的脉冲信号是不通过ATmega16内部的预分频器的。
通常对外部输入的脉冲信号的基本处理有两种: ? 对外部的脉冲信号进行计数,即记录脉冲的个数,一旦记录的脉冲个数到达一设定
值时进行必要的处理。
? 对外部的脉冲信号的频率(周期)进行测定。
在本小节中,我们只介绍前一种的应用。关于对外部的脉冲信号的频率(周期)进行测定的设计,将在本书后面的相关章节中介绍。 例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的程序生成向导,在它的帮助下生成一个程序框架后,然后再加入自己的程序和进行必要的修改。
,基于AVR的单片嵌入式系统原理与实践应用
图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
// Timer 0 溢出中断服务
interrupt [TIM0_OVF] void timer0_ovf_isr(void) { }
void main(void) {
PORTA=0x01; DDRA=0x01;
// 设置PA0输出方式
TCNT0=0x83;
// 重新设置TCNT0的初值 // PA0取反输出
PORTA.0 = ~PORTA.0;
华东师范大学 电子系 马 潮 8-15