Variables Delay in ISR

OP #1094163
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
Gast #1094196
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.
Gast #1094231
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren