Forum: Compiler & IDEs Variables Delay in ISR


von Sven S. (schwerminator)


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:
1
ISR(INT0_vect){
2
  pcf8583_set_alarm_int(0);
3
  
4
  //Fehlalarm ausschließen
5
  if(!(timerarray[0].set == 0 && timerarray[1].set == 0)){
6
    if(timerarray[0].set == 1){
7
      makro(timerarray[0].makro_id);
8
      timerarray[0].alarm_int = 0;
9
    }
10
    else if(timerarray[1].set == 1){
11
      makro(timerarray[1].makro_id);
12
      timerarray[1].alarm_int = 0;
13
    }  
14
    
15
    timer_event = 1;
16
  }
17
  
18
//  sort_timer();
19
}
1
void makro(uint8_t id){
2
  dogm_clear();
3
  dogm_puts_P("Sende Makro:");
4
  dogm_gotoxy(0, 1);
5
  char buffer[17];
6
  strcpy_P(buffer, makro_zuordnung[id].label);
7
  dogm_puts(buffer);
8
  
9
  uint16_t makro_pntr = pgm_read_word(&makro_zuordnung[id].makro);
10
  uint8_t device, rpt;
11
  uint16_t data, rpt_delay, delay;
12
  
13
  for(uint8_t i=0; i<pgm_read_byte(&makro_zuordnung[id].cmds); i++){
14
    device = pgm_read_byte(makro_pntr++);
15
    data = pgm_read_word(makro_pntr++); makro_pntr++;
16
    rpt = pgm_read_byte(makro_pntr++);
17
    rpt_delay = pgm_read_word(makro_pntr++); makro_pntr++;
18
    delay = pgm_read_word(makro_pntr++); makro_pntr++;
19
    
20
    for(uint8_t j=0; j<rpt; j++){
21
      switch(device){
22
        case 1:  SIRC(data); break;    // TV
23
        case 2:  NEC(data, 1); break;  // DVB-T
24
        case 3:  NEC(data, 2); break;  // DVD
25
        case 4:  JAPAN(data); break;    // Receiver
26
      }
27
      
28
      if(j != (rpt-1)){
29
        counter_ms = 0;
30
        while(counter_ms <= rpt_delay);
31
      }
32
    }
33
    
34
    counter_ms = 0;
35
    while(counter_ms <= delay);
36
  }
37
}
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

von Rolf Magnus (Gast)


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.

von STK500-Besitzer (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.