新闻中心

EEPW首页>嵌入式系统>设计应用> ATMAGE16定时器0初始值计算总结

ATMAGE16定时器0初始值计算总结

作者: 时间:2016-11-23 来源:网络 收藏
今天在学习利用定时器0完成定时时发现在计算初始值时,不是很明白如何计算,就在网上找答案,看了很多人的例子和讲解总算是有点头绪了,先把那些有用的资料整理在一起供以后使用!谢谢各位在网上分享他们学习成果的大虾小虾和给为泡泡叔叔!!!

本文引用地址://m.amcfsurvey.com/article/201611/320231.htm

定时器0是8位的故可计数的范围是0-255这些数,我们在设置初始值时就就应该告诉计数器我们开始计数的位置,这也就是TCNT0的初始值,当计数到255时,有硬件在TIFR的bit0位TOV0置位触发中断,如果要使用比较匹配中断时就要告诉OCR0定时器计数的数值(也就是256-m,m为TCNT0的初始值),定时器记了多少数到达TOP值,当发生比较匹配值相同时在TIFR的bit1位OCF0置位从而触发中断!

以上是我学习过程的一点小总结,我会慢慢的将他弥补上的,如果说对了,有看到的网友有什么意见和建议给我留一下言我好肯定一下,如果说错了,给为大虾小虾也不要笑话我,请您也给我留下言,好给我指正我的错误和建议!在这里也谢谢你们了!!

首先依照AVR使用范例--定时器应用范例

http://www.avrvi.com/avr_examples/timer.html,使用ICC application bulider快速配置定时器生成代码如下:

//ICC-AVR application builder : 2007-8-28 0:55:55
// Target : M16
// Crystal: 7.3728Mhz

#include
#include

void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}

TIMER0 initialize - prescale:1024

// WGM: Normal

// desired value: 20mSec

// actual value: 19.861mSec (0.7%)

voidtimer0_init(void)
{


TCCR0 = 0x00;//stop

TCNT0 = 0x71;//set count
OCR0= 0x 8F;//set compare
TCCR0 = 0x05;//start timer

这三位设置为1 0 1 :定时器的时钟为外部时钟频率的1024分频*/
}

#pragmainterrupt_handler timer0_comp_isr:20
voidtimer0_comp_isr(void)
{
//compare occured TCNT0=OCR0
}

#pragma interrupt_handler timer0_ovf_isr:10
voidtimer0_ovf_isr(void)
{
TCNT0 = 0x71;//reload counter value
}

//call this routine to initialize all peripherals
voidinit_devices(void)
{
//stop errant interrupts until set up
CLI();//disable all interrupts
port_init();
timer0_init();

MCUCR = 0x00;
GICR= 0x00;
TIMSK = 0x03;//timer interrupt sources
SEI();//re-enable interrupts
//all peripherals are now initialized
}

这里将以上程序用到的Time0寄存器如下所示:

T/C0控制寄存器TCCR0
/FOC0/WGM00/COM01/COM00/WGM01/CS02/CS01/CS00TCCR0

76543210

Bit 7 – FOC0: 强制输出比较

Bit 6, 3 – WGM01:0: 波形产生模式

Bit 5:4 – COM01:0: 比较匹配输出模式

Bit 2:0 – CS02:0: 时钟选择

MCU 控制寄存器- MCUCR

MCU 控制寄存器包含了电源管理的控制位

SM2/SE/SM1/SM0/ISC11/ISC10/ISC01/ISC00MCUCR

76543210

Bits 7, 5, 4 – SM2..0:休眠模式选择位 2、1 和0

SM2 SM1 SM0休眠模式
000空闲模式
001ADC 噪声抑制模式
010掉电模式
011省电模式
100保留
101保留
110Standby(1) 模式
111扩展Standby(1) 模式

Bit 6 – SE: 休眠使能

Bit 3, 2 – ISC11, ISC10: 中断1 触发方式控制

Bit 1, 0 – ISC01, ISC00: 中断0 触发方式控制

通用中断控制寄存器- GICR

7654 3 210
INT1 INT0 INT2– – –IVSEL IVCEGICR

Bit 7 – INT1: 使能外部中断请求 1

Bit 6 – INT0: 使能外部中断请求 0

Bit 5 – INT2: 使能外部中断请求 2

Bit 1 – IVSEL: 中断向量选择

Bit 0 – IVCE: 中断向量修改使能

T/C 中断屏蔽寄存器- TIMSK

76543210
OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0TIMSK

Bit 1 – OCIE0: T/C0 输出比较匹配中断使能

Bit 0 – TOIE0: T/C0 溢出中断使能

其余的未定义可参考ATMEGA16 datasheet!

上面啰嗦了很多,以后看的时候不用到处去翻datasheet,这里说TCNT0的初始值

TCNT0 = 0x71;//set count
OCR0= 0x8F;//set compare

如何得到这两个值呢?

现假设最大计数值为M,timer0为8位,那M=256。(这是我看51的定时器/计数器的基本结构及工作原理,AVR应该差不多的吧,反正我后来用计算器算了一下,符合就得)

计数器初值X的计算式为:

X=M-比较值(计数值)

定时工作方式的计数初值X等于:

X = M -比较值= M - t / T = M - (* t) / prescal

为T/C0最高频率的时钟源,prescal为预分频数。

现在我们知道

TCNT0 = 0x71;// set count十进制的113
OCR0= 0x8F;// set compare十进制的143

就相当于OCR0是计数值,TCNT0是初始值。TCNT0=113,那么OCR0=M- TCNT0=143。

我们取=7.3728Mhz,prescal=1024,于是,我们利用公式得出比较值=144,和结果的143有点误差。接着呢,我们试着用公式倒推,算t

t =(143*1024)/(7.3728**)= 19.86111````ms

刚好和设置那里的actual value误差一样。所以说,以倒推的为准取TCNT0和OCR0值

最后呢,TCCR0 = 0x05;//start timer

TCCR0预分频1024,具体可见上图,

应该提醒的是:

8位的定时器timer0根据公式,它最多可以完成35ms的定时任务,1秒的任务它不能完成,所以当想用来定时1秒的时候,只能用16位的定时器了;

且atmega128和atmega16的timer0选择时钟源是不一样的。请千万要注意。现在我们讨论的是atmega16;

还有上边的讨论是在工作模式(waveform mode)选择normal情况下。其他模式初始值和比较值的不一样的,具体你可以选择其他模式看一下它的变化值。

这样就得到了我们想要的TCNT0和OCR0的初始值了!



评论


技术专区

关闭