ATmega32单片机片内的T/C2模块功能非常接近与T/C0,它最大的特点就是可以使用外接与TOSC1和TOSC2引脚的晶体振荡器作为计数时钟,使其可以在低功耗的状态下实现实时时钟(RTC)的功能。
10.1
认识T/C2
10.1.1
T/C2的内部结构
T/C2的内部由计数器单元、输出比较单元和同步控制单元三部分构成,具体如图10-1所示。
1.计数器单元
T/C2的核心部分是一个可编程8位双向计数单元,称为TCNT2,它可以由来自系统的同步时钟驱动,也可以由外接于TOSC1和TOSC2引脚的异步时钟驱动。这两种时钟信号均需经过独立的预分频器后,输出clk 2.输出比较单元
输出比较单元用于持续地将计数器TCNT2的值与输出比较寄存器OCR2的值作比较,一旦发现二者相等,比较器立即产生一个匹配信号,并在下一个定时器时钟到来时置位OCF2标志位,如果此中断得到允许,将引发输出比较中断。中断执行后,标志位OCF2自动清零,也可以通过软件对该位写1以清零此标志位。
波形发生器利用比较结果产生PWM波形或在比较输出引脚OC2输出可变频率的信号。当T/C2工作在比较输出模式或PWM模式时,引脚OC2的功能由配置寄存器使能(TCCR2寄存器的COM21:COM20位),但引脚的方向需要设定为输出。
3.同步控制单元
同步控制单元用于控制T/C2的工作状态,它决定T/C2是工作于使用系统时钟的同步状态还是使用外部时钟的异步状态。工作状态的设定是通过异步状态寄存器ASSR的AS2位来实现的,通过ASSR寄存器,还可以对TCNT2及OCR2寄存器的状态进行监控。
10.1.2
T/C2的工作模式
按照配置的不同,T/C2可以配置成以下几种模式:
1.普通模式(定时器模式)
普通模式是最基本的工作模式,在此模式下,计数器TCNT2的值在计数时钟的驱动下不停地累加,当计数到达最大值0xFF后,在下一个时钟到来时产生计数溢出,计数值返回到0x00并重新开始计数。在计数器TCNT2为0x00的同时,T/C2溢出标志位TOV2置位。如果T/C2溢出中断得到使能,就会引发单片机执行中断服务程序,一旦中断服务程序得到执行,TOV2标志位会硬件清零。在普通模式下,用户可以随时软件写入寄存器TCNT2。
2.CTC模式(比较匹配清零定时器模式)
在此模式下输出比较寄存器OCR2用于保存匹配值,计数器TCNT2的值持续累加,当TCNT2的值等于OCR2时,二者产生匹配,随后计数器TCNT2的值会清零,并且相应的中断标志位OCF2会置位,如果此中断得到使能,即可执行中断服务程序。T/C2的CTC模式时序如图10-2所示。
在CTC模式下,将引脚OC2的数据方向设定为输出,引脚上将会产生电平变化,具体变化方式由T/C2控制寄存器TCCR2的COM21:COM20位决定。为了使OC2引脚能输出正确的波形,可以将引脚电平变化的方式设定为比较匹配时电平取反,其频率可由下式计算:
比较器输出频率=系统时钟(或异步时钟)/[2×N×(1+寄存器OCR2值)]
在上面的公式中,N为预分频因子,其值可以为1、8、32、64、128、256或1024。
3.快速PWM模式
快速PWM模式是基于单斜坡操作的,这有利于产生更高频率的PWM波形。在快速PWM模式下,计数器从BOTTOM计到MAX,然后立即返回到BOTTOM并重新开始计数。当计数器TCNT2的值与OCR2的值匹配时,引脚OC2上的电平将会按照TCCR2寄存器COM21:COM20位设定的方式动作。T/C2的快速PWM模式时序如图10-3所示。
与T/C0相同的是,T/C2在快速PWM方式下,由于计数器TCNT2的计数值是从BOTTOM计到MAX,所以PWM的周期也是一个固定的值,在图10-3中,快速PWM的工作过程如下:
·A点:计数器的值为最小值BOTTOM,此时OC2引脚输出高电平。
·B点:计数器TCNT2的值不断累加到与OCR2的值匹配时,OC2引脚电平翻转并输出低电平,输出比较中断标志位OCF2置位。
·C点:计数器TCNT2计数达到最大值MAX,T/C2的溢出标志位TOV2置位,此时OCR2寄存器中保存的值会进行一次更新,此更新可以改变PWM波形的占空比。
·D点:计数器TCNT2由于溢出而清零到BOTTOM,OC2引脚电平翻转,输出高电平。
快速PWM模式下的输出频率可由下式计算:
PWM频率=系统时钟频率(异步时钟频率)/(N×256)
在上面的公式中,N为预分频因子,其值为1、8、32、64、128、256或1024。
4.相位修正PWM模式
相位修正PWM模式是基于双斜坡操作的。在此模式下,计数器TCNT2重复地从BOTTOM计数到MAX,然后再从MAX倒退计数到BOTTOM。T/C2的相位修正PWM模式的时序如图10-4所示。
在图10-4所示的相位修正PWM模式中,其工作方式如下:
·A点:计数器TCNT2因上一次计数达到MAX值,这时比较匹配寄存器OCR2的值得到更新,这个更新可以用于改变PWM波形的占空比,也是一个新PWM周期的开始,此时OC2引脚电平翻转,按照COM21:0位的设定,引脚输出低电平。
·B点:计数器TCNT2反向计数到OCR2指定的匹配值,这时输出比较标志位OCF2置位,按照COM21:COM20位的设定,引脚OC2电平再次翻转,输出高电平。
·C点:计数器清零并重新开始正向计数,计数器溢出且中断标志位TOV2置位。
·D点:计数器TCNT2正向计数到OCR2指定的匹配值,引脚OC2输出低电平,输出比较标志位OCF2置位。
·E点:计数器TCNT2正向计数到达最大值MAX,比较匹配寄存器OCR2的值再次得到更新,本次PWM周期结束。
相位修正PWM方式的输出频率可由下式计算:
PWM频率=系统时钟频率(异步时钟频率)/(N×510)
N为预分频因子,其值可为1、8、32、64、128、256或1024。
10.2
T/C2的控制
10.2.1
T/C2的相关寄存器
1.TCCR2寄存器
该寄存器是T/C2的控制寄存器,包含了多个T/C2的模式控制位和比较匹配单元输出模式控制位。
TCCR2寄存器:T/C2控制寄存器
bit 7FOC2:强制输出比较控制位。该位置1时将强制OC2引脚进入比较匹配的状态,具体由COM21:COM20位设定。强制输出比较匹配状态不会引发中断,而且此位只在非PWM模式时有效,在PWM模式下不可将该位置1。
bit 6,3WGM21:WGM20:波形发生模式设定位,用于设定T/C2的工作状态,具体详见表10-1。
bit 5:4COM21:COM20:比较匹配输出模式设定位(OC2引脚),具体详见表10-2。
bit 2:0CS22:CS20:T/C2时钟源选择位,用于选择T/C2的时钟源或设定预分频比,具体详见表10-3。
注意:虽然引脚OC2的比较输出状态由寄存器TCCR2的COM21:COM20位控制,但它也同时受引脚的方向寄存器控制,使用时需要将其设定为输出,才能在OC2引脚上正常输出信号。
2.TCNT2寄存器
该寄存器是T/C2的数据寄存器,用于保存定时或计数值,TCNT2寄存器可以随时读写。
TCNT2寄存器:T/C2的数据寄存器
3.OCR2寄存器
T/C2的输出比较寄存器,该寄存器中的数值与TCNT2的计数值进行连续的比较,一旦数据匹配,将产生一个输出比较中断,并且可以改变OC2引脚的电平状态。
OCR2寄存器:输出比较寄存器
4.ASSR寄存器
T/C2的异步状态控制寄存器,包含了多个T/C2异步工作状态设定位以及T/C2的相关状态位。
ASSR寄存器:异步状态寄存器
bit 7-4未用位。
bit 3AS2:T/C2异步模式选择位。该位置1时T/C2由连接于TOSC1和TOSC2引脚的晶体振荡器驱动,清零时T/C2由系统时钟驱动。
bit 2TCN2UB:T/C2更新状态位。当T/C2工作在异步模式时,写TCNT2寄存器将引起TCN2UB位置1,TCNT2寄存器更新完毕后,TCN2UB位硬件清零。
bit 1OCR2UB:输出比较寄存器2更新状态位。当T/C2工作在异步模式时,写OCR2寄存器将引起OCR2UB位置1,OCR2寄存器更新完毕后,TCN2UB位硬件清零。
bit 0TCR2UB:T/C2控制寄存器更新状态位。当T/C2工作在异步模式时,写TCCR2寄存器将引起TCR2UB位置1,TCCR2寄存器更新完毕后,TCR2UB位硬件清零。
注意:当更新标志位TCN2UB、OCR2UB和TCR2UB位清零时,即表示可以向其相关寄存器中写入新值。如果在更新标志位为1时写入上述相关寄存器将会破坏数据。
5.TIMSK寄存器
该寄存器是T/C的中断屏蔽寄存器,该寄存器包含了多个定时/计数器的中断控制位。
TIMSK寄存器:T/C中断屏蔽寄存器
bit 7OCIE2:T/C2输出比较匹配中断使能位。该位置1时,T/C2输出比较匹配中断使能。
bit 6TOIE2:T/C2溢出中断使能位。该位置1时,T/C2溢出中断使能。
bit 5-0暂不介绍。
6.TIFR寄存器
该寄存器是T/C的中断标志寄存器,该寄存器包含了多个定时/计数器的中断标志位。
TIFR寄存器:T/C中断标志寄存器
bit 7OCF2:T/C2输出比较匹配标志位。当TCNT2与OCR2匹配时该位置1。当此中断服务程序被执行后,该位自动清零。软件对该位写1会清零此标志位。
bit 6TOV2:T/C2溢出标志位。T/C2溢出时该标志位置1,当此中断服务程序被执行后,该位自动清零。软件对该位写1会清零此标志位。
bit 5-0:暂不介绍。
10.2.2
T/C2的预分频器
ATmega32单片机的T/C2模块具有自己独立的预分频器,其结构如图10-5所示。
T/C2预分频器的输入时钟称为clk SFIOR寄存器。该寄存器是特殊功能IO寄存器,包含了多个与A/D转换、模拟比较器相关的功能控制位。
SFIOR寄存器:特殊功能IO寄存器
bit 7-2:暂不介绍。
bit 1PSR2:T/C2预分频器复位控制位。该位置1时T/C2的预分频器复位,操作完成后该位硬件清零。
bit 0:暂不介绍。
10.3
T/C2的编程应用
T/C2模块的特点是可以使用外接于TOSC1和TOSC2引脚的晶振作为时钟信号,利用这一特点可以使单片机在低功耗模式下维持时钟的运行。以下我们要使用T/C2模块,配合外接的晶振,制作另外一款数显电子钟。打开Atmel Studio 6.1软件,新建名为“TC2RTC”的项目,保存在chapter10文件夹下,软件会将名为TC2RTC.c的源文件自动添加到新建的项目中,编辑TC2RTC.c源文件,具体代码详见代码清单10-1。
代码清单10-1
基于T/C2的实时时钟
/*
*
TC2RTC.c *
TC2
实时时钟+
数码管显示
*
Created: 2013/9/15
21:06:39
*
Author: GAO */
#include
//
包含AVR 头文件
#include
//
包含AVR 中断控制头文件
#define F_CPU 16000000UL //
定义系统时钟
#include
//
包含延时函数头文件
unsigned char table0[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f }; //
共阴无点
unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed, 0xfd,0x87,0xff,0xef }; //
共阴有点
unsigned int SEC,NUM; //
定义秒变量,显示变量
void display(unsigned int NUM); //
数码管显示函数声明
void TC2_init(void); //
定时器2
初始化函数声明
int main(void)
{
DDRA=0xFF; //
设数码管段驱动端为输出
DDRB=0xF0; //
设数码管位驱动端为输出
TC2_init(); NUM=510; //
设定最初时间为08:30
while(1)
{
display(NUM); }
}
/**********
数码管显示函数**********/
void display(unsigned int NUM)
{
unsigned char NUM4,NUM3,NUM2,NUM1; NUM1=NUM%10; NUM2=NUM%60/10; NUM3=NUM%600/60; NUM4=NUM/600; PORTA=table0[NUM1]; PORTB=0x10; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms PORTA=table0[NUM2]; PORTB=0x20; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms if(SEC%2==1)
//
点闪烁
{
PORTA=table0[NUM3]; PORTB=0x40; _delay_ms(2); //
延时2ms }
else {
PORTA=table1[NUM3]; PORTB=0x40; _delay_ms(2); //
延时2ms }
PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms PORTA=table0[NUM4]; PORTB=0x80; _delay_ms(2); //
延时2ms PORTA=0x00; PORTB=0x00; _delay_ms(1); //
延时1ms }
/**********T/C2
初始化函数**********/
void TC2_init(void)
{
SREG=0x80; TIMSK=0x40; //
开T/C2
溢出中断
TCNT2=(256-128); //
初值128,32768/256=128Hz TCCR2=0x06; //
设定T/C2
普通模式,预分频比1/256
ASSR=0x08; //
开T/C2
异步模式
}
/**********T/C2
中断服务函数**********/
ISR(TIMER2_OVF_vect)
{
TCNT2=(256-128); //
初值128
,周期1S SEC++; if(SEC>=60)
{
SEC=0; NUM++; }
if(NUM>=1440)
{
NUM=0; }
}
/**********
结束**********/
将以上代码编译后,下载到AVR系统板中,程序运行后如图10-6所示。数码管显示当前时间为“08.30”,时与分之间的小数点以秒为周期闪烁,指示时钟正在运行。这里需要特别说明的是,此时T/C2的运行已经不再需要系统时钟的支持了。
通过前面的学习,我们已经掌握了ATmega32单片机定时/计数器的基本用法,这也是学好AVR单片机的关键所在。AVR单片机定时/计数器功能之强大在主流的8位单片机中可谓无出其右,灵活地使用这三个定时/计数器可以帮助你开发出诸如时钟、信号发生器、频率计以及PWM控制器等诸多与时间相关的衍生产品。