硬件:带有ATmega328P的Arduino Uno
软件:Atmel Studio 6.2.1153,Arduino 1.0.6
计算1s所需的周期
我的代码
OCR1AH = 0x3D; //Load higher byte of 15624 into output compare register
OCR1AL = 0x08; //Load lower byte of 15624 into output compare register
TCCR1A = 0b00000000;
TCCR1B = 0b00001101; //Turn on CTC mode and prescaler of CLK/1024
while((TIFR1 & (1<<OCF1A)) == 0); //If OCF1A is set (TCNT1 = OCR1A), break
TCCR1A = 0;
TCCR1B = 0; //Stop the timer
TIFR1 &= ~(1<<OCF1A); //Clear OCF1A for the next time delay
当我点击&#34;开始调试和中断&#34;并且&#34;跨过&#34;以上代码作为函数。它总是告诉我&#34;跑步&#34;马不停蹄。为什么?怎么解决?
感谢您的帮助。
答案 0 :(得分:1)
您的配置看起来不错。
当您在调试器中暂停执行代码时,外设(独立于CPU)不会停止。某些架构/微控制器具有额外的硬件寄存器,用于在调试器停止执行代码时停止外设(例如DMA或定时器)。无论如何,AVR没有。
如果您在模拟中运行代码,您应该能够逐步查看按指令设置的所有寄存器。我建议您关闭代码优化以进行调试。
为了在硬件中调试代码(在AVR架构的情况下),您需要额外的调试器。 Arduino提供的调试仅使用在MPU中运行代码的软件,在某些情况下您无法依赖它。
无论如何,你的代码看起来是正确的。唯一的错误:将逻辑1写入TIFR1以清除位。
您应该在循环中运行您的代码以检查计时器是否正常工作:
OCR1AH = 0x3D; //Load higher byte of 15624 into output compare register
OCR1AL = 0x08; //Load lower byte of 15624 into output compare register
TCCR1A = 0b00000000;
TCCR1B = 0b00001101; //Turn on CTC mode and prescaler of CLK/1024
while(1)
{
while((TIFR1 & (1<<OCF1A)) == 0); //If OCF1A is set (TCNT1 = OCR1A), break
//Blink LED here
TIFR1 = (1<<OCF1A); //Writing logic 1 to that register clears it
}
当然如果您不想在循环中运行代码,只需将其删除即可。该代码仅用于测试目的。
修改强>
请查看Atmega328数据表:http://www.atmel.com/Images/doc8161.pdf,第139-140页,TIFR1寄存器,第1位 - OCF1A:
执行相应的中断时,硬件清零OCF1A。也可以通过向该位写入逻辑1来清除OCF1A。
有些位硬件寄存器(通常只能由用户清零,永远不能由用户设置)可以通过写入来清除1.当设置0 连接到位值>写1 给它。写入0被忽略,不会影响寄存器/位值。这可以防止从软件设置位,此时可以仅使用硬件设置位(该情况 - 定时器)。想一想 - 从代码中设置输出比较寄存器是没有意义的。其他操作(读取值,清除位)有意义并且是允许的。
还有一些寄存器只能写入,而不能读取(即读取总是返回相同的值)。
使用硬件寄存器时,请记住始终在数据表中检查如何设置/清除位。