在 atmega328p 中使用定时器 1 溢出中断闪烁 LED
blinking a led using timer 1 overflow interrupt in atmega328p
我正在尝试使用 ISR 使 LED 闪烁 3 秒,这里使用的是 atmega328p。我正在尝试使用 TIMER1(16 BIT) 在 isr 中创建 1 秒的延迟,然后将其循环 3 秒。 LED接PD7,不知道为什么不闪,谁能指出错误。我用的是simulIDE,这是电路,timer_circuit
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 0xC2F8; // decimal value is 49912
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //1024 prescaler
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
TIMSK1 |= TOIE1;
if(count>=3)
{
SET_BIT(PORTD,PD7);
count=0;
}
}
;
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
}
此代码永远不会关闭 LED ...一旦设置了该位,您的代码就永远不会清除它...尝试切换该位而不是设置它
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
TCNT1 = 0xC2F8; // reset counter
}
更新
- 在 count 变量之前使用
volatile
访问修饰符来告诉编译器您将从 ISR 更改它以确保 count
变量不会被删除在优化中
- 当您设置
TCCR1B
时,您必须将其他位设置为零才能在正常模式下运行
- 重新计算 8 MHz 的值
TCNT1
,这是内部默认频率
完整代码
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
volatile unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
}
}
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}
我正在尝试使用 ISR 使 LED 闪烁 3 秒,这里使用的是 atmega328p。我正在尝试使用 TIMER1(16 BIT) 在 isr 中创建 1 秒的延迟,然后将其循环 3 秒。 LED接PD7,不知道为什么不闪,谁能指出错误。我用的是simulIDE,这是电路,timer_circuit
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 0xC2F8; // decimal value is 49912
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //1024 prescaler
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
TIMSK1 |= TOIE1;
if(count>=3)
{
SET_BIT(PORTD,PD7);
count=0;
}
}
;
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
}
此代码永远不会关闭 LED ...一旦设置了该位,您的代码就永远不会清除它...尝试切换该位而不是设置它
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
TCNT1 = 0xC2F8; // reset counter
}
更新
- 在 count 变量之前使用
volatile
访问修饰符来告诉编译器您将从 ISR 更改它以确保count
变量不会被删除在优化中 - 当您设置
TCCR1B
时,您必须将其他位设置为零才能在正常模式下运行 - 重新计算 8 MHz 的值
TCNT1
,这是内部默认频率
完整代码
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
volatile unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
}
}
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}