2016-11-14 2 views
1

У меня есть задача запрограммировать два таймера, где я показываю что-то на своем ЖК-дисплее. У меня есть матрица клавиатуры, где я могу ввести в некоторые базовые вещи, как цифры и некоторые буквы с этим кодом:Застрял до задержки в подпрограмме

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';} 

} 

Когда я набираю в первом Таймера (Timer0) keyboard_read() работает нормально, но когда я иду во второй таймер (Timer2) keyboard_read() останавливается при команде задержки. Когда я попытался поместить key_read() в loop(), он все равно останавливается при команде задержки (в данный момент эта команда отсутствует в цикле).

Код для 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 

Код для Таймер2:

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 программе() к югу или таймерами, чтобы заставить его работать?

Заранее благодарим за любую помощь.

+0

Вы должны закончить ISR как можно скорее, а это означает, что вы не должны использовать задержку вообще (или любое другое трудоемкое занятие). Внутри ISR вы должны просто установить некоторые флаги, а затем обработать их внутри цикла. Также таймер 0 используется функцией задержки и другими функциями сохранения времени. –

+1

Вы также вызываете 'loop();' внутри вашего таймера 2 ISR. –

ответ

1

Вы можете прочитать статью об прерываниях: How do interrupts work on the Arduino Uno and similar boards? на Arduino SE Ник марс

И коротко:

  • прерывание должно быть как можно короче. Если вам нужна задержка, вы делаете это неправильно, и вы можете обработать ее в цикле позже. Просто установите флаг (или вы можете использовать флаг переполнения COMPA напрямую без его прерывания, вам просто нужно проверить этот флаг и очистить его, введя в него логику 1)
  • Вы не можете использовать Arduinos delay, так как ему нужен таймер/счетчик 0 переполнение прерывания. И все прерывания блокируются в обработчике ISR автоматически. Таким образом, вы ждете изменения миллисов, которые никогда не произойдут.
  • Также вы не можете использовать что-либо еще, что может относиться к другому прерыванию. Например, Serial.write/print работает до тех пор, пока буфер отправки не будет заполнен, а затем появится тупик.
  • Почему вы звоните loop()? Он вернется к прерванному коду сразу после завершения обработки обработчиком.