atmega 328p 中断和定时器设置 [C/C++]
atmega 328p interrupt and timer setup [C/C++]
我正在尝试设置一个中断和一个 counter/timer。中断是外部的,从引脚读取低逻辑。计时器应每 100 us 递增一次,加起来为 count
变量。
我已经设置了中断,它工作正常但是,在设置定时器之后,中断和定时器都不起作用。代码是这样的:
volatile boolean allowCount = false, timerFlag = false;
volatile unsigned int counter;
boolean pulseLow = false;
void setup(){
Serial.begin(9600);
// initialize external pin interrupt.
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10); // set wanted flags (low logic level causes interrupt)
PCMSK1 = 0b00010000; // Enable Pin Change Interrupt for A4
// TODO Interrupt settings not working together
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 0x18;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 64 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS11);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
}
void loop(){
if (allowCount == true)
{ timer100_uS();
if (counter > 50 && pulseLow == false){
DDRC |= (1 << DDC3 ); // sets bit DDC3 to 1 within register DDRC
//set pin 3(A3) ouput as sourcing Vcc(HIGH)
PORTC |= (1 << PORTC3);
timerReset();
pulseLow = true;
}
if (pulseLow == true){
timer100_uS();
if (counter >= 500){
//set pin3 of port C to LOW (A3);
PORTC &= ~(1 << PORTC3);
pulseLow = false
timerReset();
}
}
// external pin interrupt
ISR(PCINT1_vect){
if (allowCount == false)
allowCount = true;
}
// timer/counter interrupt
ISR (TIMER1_COMPA_vect)
{
if (timerFlag == true){
counter++;
}
}
void timer_100uS(void){
timerFlag = true;
cli();
}
void timerReset(void){
sei();
timerFlag = false;
counter = 0;
}
使用预分频器 64 和 16 MHz 处理器根据以下公式计算 OCR0A 的值为 24 (0x18):
OCRn = [ (clock_speed / Prescaler_value) * Desired_time_in_Seconds ] - 1
如何设置不同的中断,使它们不相互重叠?
或者更好的是,是否可以设置定时器使其不使用中断?
感谢阅读!
如我所见,您正在使用带有 Arduino 库的 ATMega328。您的问题是 Arduino 库在内部使用 Timer 1 用于其内部目的。因此,如果您为定时器 1 添加自己的中断处理程序,您将覆盖 Arduino 的定时器 1 中断处理程序,这会破坏库。
如果您想继续使用 Arduino 库,也可以使用该库来控制定时器:Arduino Timer1
感谢@old_timer、@klasyc 的回答。
很晚了,但我通过在设置中使用 timer0 而不是 timer1 并使用以下设置解决了这个问题:
// initialize external pin interrupt.
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10); // set wanted flags (falling edge causes interrupt)
PCMSK1 = 0b00001000; // Enable Pin Change Interrupt for A3
TCCR0B = 0;
TCCR0A = 0;
//set CTC mode
TCCR0A = ( 1 << WGM01 );
// set OCR0A value for 1 us counter (OCRxn = (freq/prescaler)*desired_value)-1
OCR0A = 15;
// set compare match counter
TIMSK0 |= (1 << OCIE0A);
//set prescaler
TCCR0B |= ( 1 << CS00);
循环外:
ISR(TIMER0_COMPA_vect){
counter++;
}
我正在尝试设置一个中断和一个 counter/timer。中断是外部的,从引脚读取低逻辑。计时器应每 100 us 递增一次,加起来为 count
变量。
我已经设置了中断,它工作正常但是,在设置定时器之后,中断和定时器都不起作用。代码是这样的:
volatile boolean allowCount = false, timerFlag = false;
volatile unsigned int counter;
boolean pulseLow = false;
void setup(){
Serial.begin(9600);
// initialize external pin interrupt.
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10); // set wanted flags (low logic level causes interrupt)
PCMSK1 = 0b00010000; // Enable Pin Change Interrupt for A4
// TODO Interrupt settings not working together
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 0x18;
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 64 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS11);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
}
void loop(){
if (allowCount == true)
{ timer100_uS();
if (counter > 50 && pulseLow == false){
DDRC |= (1 << DDC3 ); // sets bit DDC3 to 1 within register DDRC
//set pin 3(A3) ouput as sourcing Vcc(HIGH)
PORTC |= (1 << PORTC3);
timerReset();
pulseLow = true;
}
if (pulseLow == true){
timer100_uS();
if (counter >= 500){
//set pin3 of port C to LOW (A3);
PORTC &= ~(1 << PORTC3);
pulseLow = false
timerReset();
}
}
// external pin interrupt
ISR(PCINT1_vect){
if (allowCount == false)
allowCount = true;
}
// timer/counter interrupt
ISR (TIMER1_COMPA_vect)
{
if (timerFlag == true){
counter++;
}
}
void timer_100uS(void){
timerFlag = true;
cli();
}
void timerReset(void){
sei();
timerFlag = false;
counter = 0;
}
使用预分频器 64 和 16 MHz 处理器根据以下公式计算 OCR0A 的值为 24 (0x18):
OCRn = [ (clock_speed / Prescaler_value) * Desired_time_in_Seconds ] - 1
如何设置不同的中断,使它们不相互重叠? 或者更好的是,是否可以设置定时器使其不使用中断? 感谢阅读!
如我所见,您正在使用带有 Arduino 库的 ATMega328。您的问题是 Arduino 库在内部使用 Timer 1 用于其内部目的。因此,如果您为定时器 1 添加自己的中断处理程序,您将覆盖 Arduino 的定时器 1 中断处理程序,这会破坏库。
如果您想继续使用 Arduino 库,也可以使用该库来控制定时器:Arduino Timer1
感谢@old_timer、@klasyc 的回答。 很晚了,但我通过在设置中使用 timer0 而不是 timer1 并使用以下设置解决了这个问题:
// initialize external pin interrupt.
PCICR = 0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
EICRA |= bit (ISC10); // set wanted flags (falling edge causes interrupt)
PCMSK1 = 0b00001000; // Enable Pin Change Interrupt for A3
TCCR0B = 0;
TCCR0A = 0;
//set CTC mode
TCCR0A = ( 1 << WGM01 );
// set OCR0A value for 1 us counter (OCRxn = (freq/prescaler)*desired_value)-1
OCR0A = 15;
// set compare match counter
TIMSK0 |= (1 << OCIE0A);
//set prescaler
TCCR0B |= ( 1 << CS00);
循环外:
ISR(TIMER0_COMPA_vect){
counter++;
}