Atmega8 上的时钟
Posted
技术标签:
【中文标题】Atmega8 上的时钟【英文标题】:Clock on Atmega8 【发布时间】:2014-10-11 17:18:22 【问题描述】:我正在尝试在 Atmega8 上做一个时钟。 我有 8Mhz 石英。
我使用 timer0 中断作为时钟计时:
/* Settings */
#define TMR_RELOAD 80 - 5 /* 8 kHz / 80 = 100 Hz */
#define TMR_CNT_MAX 100 /* 1Hz internal counter */
/* internal variables */
static uint8_t tmr_cnt;
inline void TMR0_Init()
/* set clock source f_t0 = 8МHz/1024 = 8 kHz */
TCCR0 = _BV(CS00) | _BV(CS02);
TIMSK |= _BV(TOIE0); /* Enable TMR0 interrupt on overflow*/
ISR (TIMER0_OVF_vect)
if (tmr_cnt == 0)
Clock_Tick1s();
tmr_cnt++;
if (tmr_cnt >= TMR_CNT_MAX)
tmr_cnt = 0;
TCNT0 -= TMR_RELOAD;
问题是我的时钟跑得太快或太慢了。
我放入 TCNT0 寄存器的计算值是 80,但在这种情况下时钟运行得太慢了。 当我使用 80-4 时,时钟也运行得太慢了。我用80-5的时候太快了。
我不知道,怎么可能???
更新: 现在设置如下,但问题依然存在。
/* Settings */
#define TMR_RELOAD 125 /* 31.25 kHz / 125 = 250 Hz */
#define TMR_CNT_MAX 250 /* 1Hz internal counter */
inline void TMR0_Init()
/* set clock source f_t0 = 8МHz/256 = 31.25 kHz */
TCCR0 = _BV(CS02);
TIMSK |= _BV(TOIE0); /* Enable TMR0 interrupt on overflow*/
ISR (TIMER0_OVF_vect)
TCNT0 -= TMR_RELOAD;
if (tmr_cnt == 0)
Clock_Tick1s();
tmr_cnt++;
if (tmr_cnt >= TMR_CNT_MAX)
tmr_cnt = 0;
【问题讨论】:
“太快”是多少?例如每小时多少秒?有示波器吗? 每 3 小时大约 5 分钟。不,我没有示波器。 【参考方案1】:请注意,当您调用时
TCNT0 -= TMR_RELOAD;
TCNT0 寄存器已经为 0。所以你得到 TCNT0 = 131,这需要 124 个滴答声才能溢出。这意味着你的时钟是
1/31250 * 250 = 8ms
每秒更快,结果是
8ms * 60 x 60 x3 = 86.4s
每 3 小时。这不是您在 cmets 中提到的 5 分钟,但错误就在那里。您的 8MHz 晶体可能会产生一些额外的错误。这取决于晶体质量以及谐振电路的设计。
我建议您使用 Timer2 的输出比较中断,而不是使用溢出中断并重新加载 TCNT 值。
“输出比较寄存器包含一个 8 位值,它与计数器值 (TCNT2) 持续进行比较。匹配可用于生成输出比较中断...”
它更容易处理,您不必处理“重新加载”计时器。
您也可以考虑使用 32.768kHz 时钟晶体。
【讨论】:
1) 以 250Hz 的频率发生中断。 1/250 = 4 毫秒。它计算 125 个 TMR0 滴答 => 1 个额外的 TMR0 计数 = 4ms / 125 = 32 uS。 32 uS * 60 * 60 = 115.2 毫秒/小时。或每 3 小时 0.35 秒。 ------- 2) “输出比较寄存器包含一个 8 位值,该值与计数器值 (TCNT2) 连续比较。匹配可用于生成输出比较中断......”为了在中断之前有自定义时间间隔,无论如何您都需要将新值加载到 TCNT2 中。 3) 今天我注意到当我离开公寓时出现了很大的延迟(每 10 小时 4 小时)。可能也是电源的问题。 4) 感谢您的帮助! @vitperov:嗯。如果寄存器 TCNT0 仅计数 124 而不是 125,则寄存器 TCNT0 为 1“滴答”关闭(1/31250 = 32us)。由于您在一秒完成之前计数到 250,因此您每秒关闭 250 * 32us -> 8ms。还是我错过了什么? 你是对的!每小时 30 秒,每 3 小时 86.4 秒。【参考方案2】:第一个问题很明显,频率为8MHz/1024=7812.5 Hz,即使用80没有意义。操作 TCNT0 也是一个问题,因为自从计数器达到零并执行中断并且代码流到达最后一条指令后,存在一些延迟。第三个是晶振频率,你确定真的是8MHz吗?因为不适当的容性负载或只是频移可能会带来时序误差。
【讨论】:
谢谢!我修复了频率分配器并将TCNT0 -= TMR_RELOAD
移动到中断函数的开头。几个小时后我们会看到它是否有帮助。谢谢!以上是关于Atmega8 上的时钟的主要内容,如果未能解决你的问题,请参考以下文章