为什么 int main() 函数仅在 ISR(ADC_vect) 执行后才一次又一次地执行?

问题描述 投票:0回答:1

我正在制作一个基于数字时钟的项目,在面包板上使用

atmega328p
。我将 4 个按钮连接到
ADC3
通道,我使用
INT0
作为启动 ADC 转换的触发器。我还启用了
TimerCounter1
来计算时间。

我在使用增加按钮增加时间时遇到了麻烦,因为

setTime(3, 30)
函数调用在
int main()
函数中并且在按下按钮后这个函数
setTime(3, 30)
被一次又一次地执行。只有当
ISR(ADC_vect)
被执行时才会发生这种情况。

这是我认为相关的代码部分:

xxx.ino

#include <avr/io.h>

int main()
{
  Serial.begin(9600);
  
  // PB5
  DDRB |= (1<<DDB5);

  // ### Want to see how many times these functions - __init__timer(), setTime(), __init__button() gets executed after the Interrupt ###
  PORTB ^= (1<<PORTB5);

  __init__timer();
  
  //setTime(3, 30);

  __init__button();

  while(1)
  { 

  }

  return 0;
}

void __init__timer()
{ 
  // Enable the global Interrupt
  SREG |= (1<<7);
  // Enable the output compare match on comapare A 
  TIMSK1 |= (1<<OCIE1A);

  // Set TimerCounter1 in CTC mode
  TCCR1A &= ~(1<<WGM10);
  TCCR1A &= ~(1<<WGM11);
  TCCR1B |= (1<<WGM12);
  TCCR1B &= ~(1<<WGM13);

  // Set the prescalr to 1024 so we get 15625 Hz pulses(counts) per second
  TCCR1B |= (1<<CS10);
  TCCR1B &= ~(1<<CS11);
  TCCR1B |= (1<<CS12);

  // Assign the OCR1A to 46875 (3 seconds)
  OCR1A = 46875;
}

ISR(TIMER1_COMPA_vect)
{ 
  Serial.println("ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled");
}

void __init__button()
{
  // Select the voltage referance - AREF pin
  ADMUX &= ~(1<<REFS1);
  ADMUX &= ~(1<<REFS0);

  // Select the input channel - ADC3
  ADMUX |= (1<<MUX0);
  ADMUX |= (1<<MUX1);
  ADMUX &= ~(1<<MUX2);
  ADMUX &= ~(1<<MUX3);

  // Configure the ADCSRA registor

  SREG |= (1<<7);
  ADCSRA |= (1<<ADIE);

  // Set the prescalar to 4 so we get 5/16 = 0.31v step size
  ADCSRA |= (1<<ADPS0);
  ADCSRA |= (1<<ADPS1);
  ADCSRA &= ~(1<<ADPS2);

  // Enable the INT0 
  EIMSK |= (1<<INT0);
  EICRA |= (1<<ISC00);
  EICRA |= (1<<ISC01);

  ADCSRB &= ~(1<<ADTS0);
  ADCSRB |= (1<<ADTS1);
  ADCSRB &= ~(1<<ADTS2);
  ADCSRA |= (1<<ADATE);

  // This will start the conversion if trigger INT0 is pressed
  ADCSRA |= (1<<ADEN);
}

ISR(ADC_vect)
{
  if((ADC < 750) && (ADC > 600))
  {
    Serial.println("Button 1 -> PB5 toggled");
  }
  if((ADC < 500) && (ADC > 350))
  {
    Serial.println("Increase time button pressed... -> PB5 toggled");
    // increaseTime();
  }
  if((ADC < 300) && (ADC > 200))
  {
    Serial.println("Decrease button pressed... -> PB5 toggled");
    // decreaseTime();
  }
  if((ADC < 200) && (ADC > 100))
  {
    Serial.println("button 4 -> PB5 toggled");
  }
}

这是串行输出:

ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
Increase time button pressed... -> PB5 toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
Increase time button pressed... -> PB5 toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
Increase time button pressed... -> PB5 toggled
I⸮Increase time button pressed... -> PB5 toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
Increase time button pressed... -> PB5 toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled
ISR(TIMER1_COMPA_vect) executed. -> PB5 Not toggled

我的问题:

为什么

int main()
函数中的指令在
ISR(ADC_vect)
执行时反复执行,而在
ISR(TIMER1_COMPA_vect)
执行时却不执行?
PB5
引脚仅在
ISR(ADC_vect)
被执行时切换。

arduino interrupt avr arduino-uno avr-gcc
1个回答
0
投票

任何函数中的代码按顺序从函数开始到结束运行一次。对于你的

main()
函数,它到达无限循环,并永远留在那里。

中断(以及附加到它们的调用向量的函数)是被乱序调用的“特殊”代码段。也就是说,它们会在需要运行时中断正常的程序流(例如发生定时器比较时),然后将 CPU 立即返回到原来的位置。

在您的情况下,无限循环点的指令流最终会达到

的效果
loop:
  nop       ; do absolutely nothing
  rjmp loop   ;go back to the "loop" label

如果发生中断,执行路径基本上如下所示:

loop:
  rjmp interrupt ;to the interrupt
  (... interrupt here ...)
  return here    ; back from interrupt
  nop       ; do absolutely nothing
  rjmp loop   ;go back to the "loop" label
© www.soinside.com 2019 - 2024. All rights reserved.