如何解决如何使Atmega328微调器中断每1秒钟滴答一次?
我有一个Atmega328p,并且已经将LED连接到它的D4引脚,我希望它每隔一秒钟打开/关闭LED。
我找到了this tutorial,并根据一些在线AVR调光计算器和我使用的12MHZ外部晶体对其进行了更改:
#define F_cpu 12000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
DDRD |= 1 << 4;
PORTD |= 1 << 4;
ICR1 = 0xB71B;
TCCR1B |= (1 << WGM12);
// Mode 4,CTC on OCR1A
TimsK1 |= (1 << ICIE1);
//Set interrupt on compare match
TCCR1B |= (1 << CS12);
// set prescaler to 256 and starts the timer
sei();
// enable interrupts
while (1)
{
// we have a working Timer
}
}
ISR (TIMER1_COMPA_vect)
{
PORTD |= 0 << 4;
// action to be done every 200ms
}
如何更改ICR1值,LED始终亮或灭。我该如何运作?
解决方法
计时器初始化看起来不错 (请参见其他答案),但是看来您没有正确切换LED。
PORTD |= 0 << 4;
不会执行任何操作。
假设您直接驱动LED,请使用PORTD |= (1 << 4);
打开LED,PORTD &= ~(1 << 4);
关闭LED,使用PORTD ^= (1 << 4);
切换输出状态。
由于您只想切换LED状态,最后一个选项显然是最佳选择,因为您不必检查输出引脚的当前状态来决定是否需要打开或关闭。
,TCCR1B |= (1 << WGM12);
// Mode 4,CTC on OCR1A
注释正确:将WGM12
位(其他WGM1x位为零)设置为打开CTC(清除定时器打开)
比较匹配)模式与OCR1A
定义的TOP值。
但是!
ICR1 = 0xB71B;
您正在将TOP值写入输入捕获寄存器ICR1
(也存在这样一种模式,其中WGM12:WGM11:wGM11:WGM10设置为1110,但是它需要使用另一个中断)。 / p>
您想将值写入OCR1A
。
12000000/256(定时器预分频器)-1 = 46874,它是0xB71A,而不是0xb71B:您忘了减去1。
由于计时器从零开始计数,因此TOP值比计时器的整个周期小1。
在这种情况下,最好使用十进制或公式来使代码更具可读性。
OCR1A = (F_CPU / 256) - 1; // 46874
也。如Rev1.0所述,您需要在中断中切换输出。
您可以使用按位互斥或^
来做到这一点:
PORTD ^= 1 << 4;
或者,在Atmega328P中,您只需向PINx
寄存器中写入1即可切换PORTx
中的位值:
PIND = 1 << 4;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。