Atmega328p 仅处理一个 ISR
Atmega328p only one ISR handled
我正在尝试 运行 两个函数 'similtaniously' 通过中断:
1) 通过定时器 0 (100Hz) 的计时测量 ADC,并在引脚 0-5 上显示结果
2) 通过引脚 6 上的计时器 1 (10Hz) 使 LED 闪烁。
问题似乎是定时器 1 的 ISR 阻塞了该函数,因此没有执行任何其他操作。这是代码:
(请不要被任何样式错误冒犯,代码正在开发中)
#define F_CPU 16000000UL // 16MHz Clock speed
#include <avr/io.h>
#include <avr/interrupt.h>
void ADC_init(void);
void SetTimer0(void);
void SetTimer1(void);
int main(void)
{
DDRB |= (1<<DDB0) + (1<<DDB1) + (1<<DDB2) + (1<<DDB3) + (1<<DDB4) + (1<<DDB5) + (1<<DDB6);
PORTB = 0b00000000;
DDRB &= ~(1<<DDB7);
ADC_init();
SetTimer0();
SetTimer1();
while(1){
}
}
void ADC_init(void)
{
cli();
// Select Vref=AVcc
// and set left adjust result
// select pin ADC0 (PC0)
ADMUX |= (1<<REFS0)|(1<<ADLAR);
//and enable ADC
//enable ADC interupt
//enable autotriggering
//set prescaller to 128
ADCSRA |= (1<<ADEN) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
//set ADC trigger source - Timer0 compare match A
ADCSRB |= (1<<ADTS1)|(1<<ADTS0);
// StartADC
ADCSRA |= (1<<ADSC);
sei();
}
//initialize timer0 match A on 100hz
void SetTimer0(void)
{
cli();
TCCR0A = 0; // set entire TCCR0A register to 0
TCCR0B = 0; // same for TCCR0B
TCNT0 = 0; // initialize counter value to 0
// set compare match register for 100Hz increments
OCR0A = 155; // = 16000000 / (1024 * 100.16025641025641)-1
// toggle PD6/OC0A pin on compare match
TCCR0A |=(1<<COM0A0)|(1<<WGM01);
//Set CTC mode
TCCR0B |= (1 << WGM01);
// Set CS02, CS01 and CS00 bits for 1024 prescaler
TCCR0B |= (1 << CS02) | (0 << CS01) | (1 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei();
}
//initialize timer1 10hz
void SetTimer1(void){
cli();
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 10 Hz increments
OCR1A = 24999; // = 16000000 / (64 * 10) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 64 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();
}
// ADC done interrupt
ISR(ADC_vect)
{
// Clear timer compare match flag
TIFR0=(1<<OCF0A);
// save ADC measurement
uint16_t val = ADC;
// show ADC results
if (val < 100)
{ PORTB = 0b00000000; }
else if (val < 300)
{ PORTB = 0b00000001; }
else if (val < 550)
{ PORTB = 0b00000011; }
else if (val < 850)
{ PORTB = 0b00000111; }
else if (val < 1020)
{ PORTB = 0b00001111; }
else
{ PORTB = 0b00011111; }
}
ISR(TIMER1_COMPA_vect)
{
//PORTB ^= PINB5;
static uint16_t on = 0;
if (on == 1){
PORTB = 0b00100000;
on = 0;
}
else {
PORTB = 0b00000000;
on = 1;
}
}
当 SetTimer1()
功能被禁用时,DCA 运行 将按预期运行。因此,单独来看,两个 ISR 都可以正常工作,但在一起时却不行。有人可以帮我解决这个问题吗?
您为 Timer0 启用了输出比较中断:
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
但没有用于该中断的 ISR 处理程序。
默认的__bad_interrupt处理程序只执行跳转到零中断向量,即重新启动程序。
这意味着如果您启用了中断,则应该有一个针对该中断的 ISR。
我正在尝试 运行 两个函数 'similtaniously' 通过中断:
1) 通过定时器 0 (100Hz) 的计时测量 ADC,并在引脚 0-5 上显示结果
2) 通过引脚 6 上的计时器 1 (10Hz) 使 LED 闪烁。
问题似乎是定时器 1 的 ISR 阻塞了该函数,因此没有执行任何其他操作。这是代码:
(请不要被任何样式错误冒犯,代码正在开发中)
#define F_CPU 16000000UL // 16MHz Clock speed
#include <avr/io.h>
#include <avr/interrupt.h>
void ADC_init(void);
void SetTimer0(void);
void SetTimer1(void);
int main(void)
{
DDRB |= (1<<DDB0) + (1<<DDB1) + (1<<DDB2) + (1<<DDB3) + (1<<DDB4) + (1<<DDB5) + (1<<DDB6);
PORTB = 0b00000000;
DDRB &= ~(1<<DDB7);
ADC_init();
SetTimer0();
SetTimer1();
while(1){
}
}
void ADC_init(void)
{
cli();
// Select Vref=AVcc
// and set left adjust result
// select pin ADC0 (PC0)
ADMUX |= (1<<REFS0)|(1<<ADLAR);
//and enable ADC
//enable ADC interupt
//enable autotriggering
//set prescaller to 128
ADCSRA |= (1<<ADEN) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
//set ADC trigger source - Timer0 compare match A
ADCSRB |= (1<<ADTS1)|(1<<ADTS0);
// StartADC
ADCSRA |= (1<<ADSC);
sei();
}
//initialize timer0 match A on 100hz
void SetTimer0(void)
{
cli();
TCCR0A = 0; // set entire TCCR0A register to 0
TCCR0B = 0; // same for TCCR0B
TCNT0 = 0; // initialize counter value to 0
// set compare match register for 100Hz increments
OCR0A = 155; // = 16000000 / (1024 * 100.16025641025641)-1
// toggle PD6/OC0A pin on compare match
TCCR0A |=(1<<COM0A0)|(1<<WGM01);
//Set CTC mode
TCCR0B |= (1 << WGM01);
// Set CS02, CS01 and CS00 bits for 1024 prescaler
TCCR0B |= (1 << CS02) | (0 << CS01) | (1 << CS00);
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
sei();
}
//initialize timer1 10hz
void SetTimer1(void){
cli();
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 10 Hz increments
OCR1A = 24999; // = 16000000 / (64 * 10) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 64 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();
}
// ADC done interrupt
ISR(ADC_vect)
{
// Clear timer compare match flag
TIFR0=(1<<OCF0A);
// save ADC measurement
uint16_t val = ADC;
// show ADC results
if (val < 100)
{ PORTB = 0b00000000; }
else if (val < 300)
{ PORTB = 0b00000001; }
else if (val < 550)
{ PORTB = 0b00000011; }
else if (val < 850)
{ PORTB = 0b00000111; }
else if (val < 1020)
{ PORTB = 0b00001111; }
else
{ PORTB = 0b00011111; }
}
ISR(TIMER1_COMPA_vect)
{
//PORTB ^= PINB5;
static uint16_t on = 0;
if (on == 1){
PORTB = 0b00100000;
on = 0;
}
else {
PORTB = 0b00000000;
on = 1;
}
}
当 SetTimer1()
功能被禁用时,DCA 运行 将按预期运行。因此,单独来看,两个 ISR 都可以正常工作,但在一起时却不行。有人可以帮我解决这个问题吗?
您为 Timer0 启用了输出比较中断:
// enable timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
但没有用于该中断的 ISR 处理程序。
默认的__bad_interrupt处理程序只执行跳转到零中断向量,即重新启动程序。
这意味着如果您启用了中断,则应该有一个针对该中断的 ISR。