在子程序延迟之前被困住了

时间:2016-11-14 14:43:03

标签: c++ timer arduino interrupt

我的任务是编程两个计时器,我在LCD-Display上显示一些东西。我有一个矩阵键盘,我可以用这个代码键入一些基本的东西,比如数字和一些字母:

void keyboard_read()
{

  digitalWrite(s1, LOW); 
  digitalWrite(s2, HIGH);
  digitalWrite(s3, HIGH);
  digitalWrite(s4, HIGH);   
  if(digitalRead(r1) == LOW){lcd.print("1"); delay(200);k++;feld[k]=1;} 
  if(digitalRead(r2) == LOW){lcd.print("4"); delay(200);k++;feld[k]=4;} 
  if(digitalRead(r3) == LOW){lcd.print("7"); delay(200);k++;feld[k]=7;} 
  if(digitalRead(r4) == LOW){lcd.print("A"); delay(200);k++;feld[k]='A';}  

  digitalWrite(s1, HIGH);   
  digitalWrite(s2, LOW);  
  digitalWrite(s3, HIGH);
  digitalWrite(s4, HIGH);   
  if(digitalRead(r1) == LOW){lcd.print("2"); delay(200);k++;feld[k]=2;} 
  if(digitalRead(r2) == LOW){lcd.print("5"); delay(200);k++;feld[k]=5;} 
  if(digitalRead(r3) == LOW){lcd.print("8"); delay(200);k++;feld[k]=8;} 
  if(digitalRead(r4) == LOW){lcd.print("0"); delay(200);k++;feld[k]=0;} 

  digitalWrite(s1, HIGH);  
  digitalWrite(s2, HIGH);
  digitalWrite(s3, LOW);  
  digitalWrite(s4, HIGH);   
  if(digitalRead(r1) == LOW){lcd.print("3"); delay(200);k++;feld[k]=3;} 
  if(digitalRead(r2) == LOW){lcd.print("6"); delay(200);k++;feld[k]=6;} 
  if(digitalRead(r3) == LOW){lcd.print("9"); delay(200);k++;feld[k]=9;} 
  if(digitalRead(r4) == LOW){lcd.print("B"); delay(200);k++;feld[k]='B';}  

  digitalWrite(s1, HIGH);   
  digitalWrite(s2, HIGH);
  digitalWrite(s3, HIGH);
  digitalWrite(s4, LOW);  
  if(digitalRead(r1) == LOW){lcd.print("F"); delay(200);k++;feld[k]='F';}  
  if(digitalRead(r2) == LOW){lcd.print("E"); delay(200);k++;feld[k]='E';}  
  if(digitalRead(r3) == LOW){lcd.print("D"); delay(200);k++;feld[k]='D';}  
  if(digitalRead(r4) == LOW){lcd.print("C"); delay(200);k++;feld[k]='C';}  

}

当我键入第一个Timer(Timer0)时,keyboard_read()工作正常,但当我进入第二个Timer(Timer2)时,keyboard_read()停止在delay命令。当我尝试将keyboard_read()放入循环()时,它仍然停在延迟命令处(此时此循环中没有此命令)。

Timer0的代码:

ISR(TIMER0_COMPA_vect)  //Durchlaufendes Menü
{
  cnt0++;
//Tastatureingabe_______________________________________________________________
  keyboard_read();

  if(feld[k]=='A')    //Abfrage nach AutoStart
  {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("AutoStart");
    TCCR0B = 0x00;  //Timer0 ausschalten
    TCCR2B = 0x07;  //Timer2 einschalten
  }
  else if(feld[k]=='E') //Abfrage nach Einstellungen
  {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("Einstellungen");  
    TCCR0B = 0x00;  //Timer0 ausschalten
    //TCCR1B = 0x00;  //Timer1 einschalten (not declared yet)
    k=0;
  }
  else if((feld[k]!=NULL))  //Falsche Eingabe Abfrage
  {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("Falsche Eingabe");  
  } //other things are not necessary

Timer2的代码:

ISR(TIMER2_COMPA_vect)    //Ausgabe der Parameter
{
  cnt2++;
  loop();
//Tastatureingabe_________________________________________________________
  keyboard_read();

  if(feld[k]=='B')    //Abfrage nach AutoStart
  {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("Zuruek");
    TCCR0B = 0x0D;  //Timer0 einschalten
    TCCR2B = 0x00;  //Timer2 ausschalten
  }
  else if((feld[k]!=NULL))
  {
    lcd.clear(); lcd.setCursor(0,0); lcd.print("Falsche Eingabe"); 
  }

我是否必须更改keyboard_read()子程序或定时器中的某些内容才能使其正常工作?

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

你可以在Nick Gammon的Arduino SE上阅读关于中断的长篇文章:How do interrupts work on the Arduino Uno and similar boards?

简而言之:

  • 中断必须尽可能短。如果你需要延迟,你做错了,你可以稍后在循环中处理它。只需设置一些标志(或者你可以在没有中断的情况下直接使用COMPA溢出标志,你只需要检查这个标志并通过将逻辑1写入其中来清除它)。
  • 您无法使用Arduinos delay,因为它需要运行T / C0溢出中断。并且所有中断都会自动在ISR处理程序中被阻止。所以你在等待改变从未发生过的毫秒。
  • 此外,你不能使用任何可能依赖于另一个中断的东西。例如,Serial.write / print一直有效,直到发送缓冲区被填满,然后出现死锁。
  • 你为什么打电话给loop()?它会在处理程序完成作业后立即返回到被中断的代码。