守时/计数器(Timer/counter)是单片机芯片中最根本的外围接口,它的用处十分广泛,常用于丈量时刻、速度、频率、脉宽、供给守时脉冲信号等。相关于一般8位单片机而言,AVR不只装备了更多的守时/计数器接口,并且仍是增强型的,功用十分强壮。ATmega128总共装备了2个8位和2个16位,共4个守时/计数器,本末节要点对它的一些增强功用的运用做根本的介绍。
5.9.1预分频器
守时/计数器最根本的功用便是对脉冲信号计数,当计数器计满后(8位为255,16位为65535),再来一个脉冲它就翻转到0,并产生中止信号。同其他单片机相似,AVR的守时/计数器的计数脉冲能够来自外部的引脚,也能够由从内部体系时钟取得;但AVR的守时/计数器在内部体系时钟和计数单元之间增加了一个预分频器,运用预分频器,守时/计数器能够从内部体系时钟取得不同频率的信号。表5-1为体系时钟为4MHz运用守时/计数器0的最高计时精度和时宽规模。
表5-1T/C0计时精度和时宽(体系时钟4MHz)
分频系数计时频率最高计时精度(TCNT0=255)最宽时宽(TCNT0=0)
14MHz0.25us64us
8500KHz2us512us
32125KHz8us2.048ms
6462.5KHz16us4.096ms
12831.25KHz32us8.192ms
25615.625KHz64us16.384ms
10243906.25Hz256us65.536ms
从表中看出,在体系时钟为4MHz时,8位的T/C0最高计时精度为0.25us,最长的时宽可抵达65.536ms。而运用16位的守时/计数器时,不需求辅佐的软件计数器,就能够十分便利的规划一个时刻长达16.777216秒(精度为256us)的守时器,这关于其它的8位单片机是做不到的。
AVR单片机的每一个守时/计数器都装备独立的、多达10位的预分频器,由软件设定分频系数,与8/16位守时/计数器合作,能够供给多种层次的守时时刻。运用时可选取最接近的守时层次,即选8/16位守时/计数器与分频系数的最优组合,减少了守时差错。所以,AVR守时/计数器的明显特色之一是:高精度和宽时规模,使得用户运用起来愈加灵敏和便利。此外,AVR的USART、SPI、I2C、WDT等都不占用这些守时/计数器。
5.9.2输入捕捉功用
ATmega128的两个16位守时/计数器(T/C1、T/C3)具有输入捕捉功用,它是AVR守时/计数器的又一个明显的特色。其根本作用是当一个事情产生时,当即将守时/计数器的值锁定在输入捕捉寄存器中(守时/计数器坚持持续运转)。运用输入捕捉功用,能够对一个事情从产生到完毕的时刻进行愈加准确,如下面的示例中准确丈量一个脉冲的宽度。
丈量一个脉冲的宽度,便是丈量脉冲上升沿到下降之间的时刻。不运用输入捕捉功用,一般状况往往需求运用两个外围部件才干完结和完成。如运用1个守时/计数器加1个外部中止(或模仿比较器):守时/计数器用于计时;而外部中止方法设置成电平改变触发方法,用于检测脉冲的上升和下降沿。当外部中止输入电平由低变高,触发中止,读取时刻1;比及输入电平由高变低时,再次触发中止,读取时刻2;两次时刻差既为脉冲宽度。这种完成方法不只多占用了一个单片机的内部资源,并且精度也遭到中止呼应时刻的约束。由于一旦中止产生,MCU呼应中止需求时刻,在中止中可能要进行恰当的中止现场维护,才干读取时刻值。而此刻的时刻值比中止产生的时刻现已滞后了。
而运用ATmega128的1个守时/计数器,再合作其输入捕捉功用来丈量脉冲的宽度就十分便利,下面是完成的程序示例。
#include
#defineICP1 PIND.4 //脉冲输入由ICP1(Pind.4)输入
unsignedcharov_counter;
unsignedintrising_edge,falling_edge;
unsignedlongpulse_clocks;
interrupt[TIM1_OVF]voidtimer1_ovf_isr(void) //T/C1溢出中止
{
ov_counter++; //记载溢出次数
}
interrupt[TIM1_CAPT]voidtimer1_capt_isr(void) //T/C1捕捉中止
{
if(ICP1)
{ //上升沿中止
rising_edge=ICR1; //记载上升沿开端时刻
TCCR1B=TCCR1B&0xBF; //设置T/C1为下降沿触发捕捉
ov_counter=0; //清零溢出计数器
}
else
{ //下降沿中止
falling_edge=ICR1; //记载下降沿时刻
TCCR1B=TCCR1B|0x40; //设置T/C1为上升沿触发捕捉
pulse_clocks=(unsignedlong)falling_edge-(unsignedlong)rising_edge
+(unsignedlong)ov_counter*0x10000/500; //核算脉冲宽度
}
}
voidmain(void)
{
TCCR1B=0x42; //初始化T/C1,1/8分频,上升沿触发捕捉
TIMSK=0x24; //答应T/C1溢出和捕捉中止
#asm(“sei”)
while(1)
{………
};
}
这段程序是在CVAVR中完成的。在T/C1的捕捉中止中,先查看ICP1的实践状况,以确定是呈现了上升沿仍是下降沿信号。假如中止是由上升沿触发的(ICP1为高电平),程序便开端一次脉冲宽度的丈量:记载下上升沿呈现的时刻,把T/C1的捕捉触发方法改为下降沿触发,并清空溢出计数器。假如中止由下降沿触发(ICP1为低电平),表明抵达脉冲的未端,程序记载下降沿呈现时刻,核算出脉冲的宽度,再将T/C1的捕捉触发方法改为上升沿触发,以开端下一次的丈量。
脉冲的实践宽度(毫秒格局)是依据T/C1的计数时钟个数来核算的。本例中T/C1的计数时钟是体系时钟(4MHz)的8分频,即500KHz,相应的计数脉冲宽度为2us。因而核算出从上升沿和下降沿之间总的计数脉冲个数,除以500个脉冲(为1ms)即得到以毫秒为单位的被测脉冲宽度了。
能够看到,运用守时/计数器以及合作它的捕捉功用丈量脉冲宽度,不只节约体系的硬件资源,编写程序简略,并且精度也高,由于读到的上升沿和下降沿的时刻便是其实践产生的时刻。