www.mikrocontroller.net

Forum: Compiler & IDEs Variables Delay in ISR


Autor: Sven S. (schwerminator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe folgendes Problem:
Ich habe eine PCF8583-RTC, die zu einer bestimmten Zeit einen Interrupt 
auslöst. Diese Interrupt-Routine ruft wiederum die Funktion makro() auf, 
in der auch Delays vorkommen. Ich weiß, dass man das eigendlich nicht 
machen soll, aber bei meiner Anwendung ist das nicht anders zu 
realisieren und auch nicht weiter schlimm. Das Problem ist nun, welches 
auch die Benutzung von delay.h ausschließt, dass das Delay variabel ist. 
Eigendlich wollte ich deshalb das Delay in makro() mit einem Timer 
realisieren, der kann aber leider keinen Interrupt auslösen, wenn 
makro() von einer Interrupt-Routine aufgerufen wurde, weil sich ISRs 
nicht gegenseitig unterbrechen. Wie kann ich also so ein dynamisches 
Delay anders realisieren?

Hier noch der Code der entscheidenen Stellen:
ISR(INT0_vect){
  pcf8583_set_alarm_int(0);
  
  //Fehlalarm ausschließen
  if(!(timerarray[0].set == 0 && timerarray[1].set == 0)){
    if(timerarray[0].set == 1){
      makro(timerarray[0].makro_id);
      timerarray[0].alarm_int = 0;
    }
    else if(timerarray[1].set == 1){
      makro(timerarray[1].makro_id);
      timerarray[1].alarm_int = 0;
    }  
    
    timer_event = 1;
  }
  
//  sort_timer();
}
void makro(uint8_t id){
  dogm_clear();
  dogm_puts_P("Sende Makro:");
  dogm_gotoxy(0, 1);
  char buffer[17];
  strcpy_P(buffer, makro_zuordnung[id].label);
  dogm_puts(buffer);
  
  uint16_t makro_pntr = pgm_read_word(&makro_zuordnung[id].makro);
  uint8_t device, rpt;
  uint16_t data, rpt_delay, delay;
  
  for(uint8_t i=0; i<pgm_read_byte(&makro_zuordnung[id].cmds); i++){
    device = pgm_read_byte(makro_pntr++);
    data = pgm_read_word(makro_pntr++); makro_pntr++;
    rpt = pgm_read_byte(makro_pntr++);
    rpt_delay = pgm_read_word(makro_pntr++); makro_pntr++;
    delay = pgm_read_word(makro_pntr++); makro_pntr++;
    
    for(uint8_t j=0; j<rpt; j++){
      switch(device){
        case 1:  SIRC(data); break;    // TV
        case 2:  NEC(data, 1); break;  // DVB-T
        case 3:  NEC(data, 2); break;  // DVD
        case 4:  JAPAN(data); break;    // Receiver
      }
      
      if(j != (rpt-1)){
        counter_ms = 0;
        while(counter_ms <= rpt_delay);
      }
    }
    
    counter_ms = 0;
    while(counter_ms <= delay);
  }
}
counter_ms ist die (volatile) Variable, die von einer Timer-ISR 
hochgezählt wird, aber das klappt ja eben nicht, wenn makro() von einer 
anderen ISR aufgerufen wurde...

Ich hoffe ihr könnt mir helfen... mfG, Sven

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Problem ist nun, welches auch die Benutzung von delay.h
> ausschließt, dass das Delay variabel ist.

Das schließt nicht die Benutzung von delay.h aus. Du darfst halt nur 
nicht _delay_us oder _delay_ms mit einer variable aufrufen. Die anderen 
Delay-Funktionen gehen immer noch, und die beiden kannst du auch nutzen, 
wenn du z.B. einfach in einer Schleife aufrufst.

> Eigendlich wollte ich deshalb das Delay in makro() mit einem Timer
> realisieren, der kann aber leider keinen Interrupt auslösen, wenn
> makro() von einer Interrupt-Routine aufgerufen wurde, weil sich ISRs
> nicht gegenseitig unterbrechen. Wie kann ich also so ein
> dynamisches Delay anders realisieren?

Indem du die ganze Arbeit in der Haupt-Programmschleife machst und in 
beiden ISRs nur Flags setzt, die dem Hauptprogramm sagen, was es als 
nächstes tun soll.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man muß ja nicht dringend notwendig auf ein Interrupt warten.
Eigentlich sollte auch irgendein Bit gesetzt werden, wenn der Timer 
einen bestimmten Wert erreicht hat. Das braucht man nur in einer 
Schleife abfragen.
Welches das Bit ist, weiß ich gerade nicht. Es dürfte vermutlich aber 
das Interrupt-Bit sein. Das wird gesetzt, sobald das entsprechende 
Ereignis eintritt - egal, ob das Interrupt-Enable-Bit gesetzt ist, oder 
nicht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.