Verschachtelte Interrupts

OP #1774402
Lesenswert?

Hallo,

Ich habe eine Lageregelung (Atmega 644p) implementiert, die mit dem 
TIMER0_COMPA_vect x-mal pro Sekunde aufgerufen wird. Nun möchte ich 
einige Variablen gerne über die serielle Schnittstelle rausschicken 
(Interruptbasierte Uart Library), allerdings wird die Übertragung durch 
die Timer Routine unterbrochen. Ich kann ja nun schlecht die Interrupts 
deaktivieren vor dem schicken, da ja dann auch das serielle nicht mehr 
läuft.
Was gibt es da für Lösungsansätze? Kann man zB die Timerinterrupts 
einzeln deaktivieren?

Vielen Dank,

David
#1774411
Lesenswert?

David P. schrieb:

> Was gibt es da für Lösungsansätze? Kann man zB die Timerinterrupts
> einzeln deaktivieren?

Wenn dir die durch den UART Interrupt verurschte Interrupt Latenz die 
Regelung ausser Tritt bringt, wirst du wohl schweren Herzens auf eine 
Interrupt getriebene UART verzichten müssen. Gerade bei der UART ist das 
auch nicht so der Beinbruch, wenn man die eigentliche 
Zeichen-Senderoutine aus der Hauptschleife heraus zyklisch aufruft.


> Nun möchte ich einige Variablen gerne über die serielle
> Schnittstelle rausschicken (Interruptbasierte Uart Library),
> allerdings wird die Übertragung durch die Timer Routine unterbrochen.

Dein Problem klingt allerdings nach einem Denkfehler:
Du kannst nicht innerhalb der Regelschleife jedesmal einen Satz 
Messwerte ausgeben, wenn die Ausgabe grundsätzlich schon mal länger 
dauert als von einem Aufruf der Regelschleife zur nächsten vergeht.
#1774461
Lesenswert?

David P. schrieb:
> Hallo Karl-Heinz,
>
> Ich würde diese Werte auch nur 1x pro Sekunde rausgeben wollen.
> Dann muss ich wohl auf die Uart Interrupt verzichten...

Ehe du das umbaust: Hast du es schon ausprobiert.
So eine UART Interrupt Routine ist ja im Normalfall eine von der kurzen 
Art: Zeichen aus Rungbuffer holen und aufs UDR zuweisen.

Klar das ist ein Arrayzugriff, ein Index erhöhen und ein paar Abfragen.

Summa summarum nichts was den µC länger als ein paar zig-Tatzyklen 
beschäftigen sollte. Wenn deine Regelschleife diese Verzögerung abkann, 
ist doch alles in Butter.
OP #1774477
Lesenswert?

Ich poste mal das Wichtigste:
1
int main(void) {
2
  
3
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
4
  uint16_t chk;
5
  char i = 0;
6
  
7
  DDRA = 0x00;
8
  PORTA = 0x00;
9
  
10
  DDRB = 0x00;
11
  PORTB = 0xFF;
12
  
13
  DDRC = 0xFF;
14
  DDRD = 0xFE;
15
  
16
  
17
  // motorcontroller disabled / PWM-Signals to zero//
18
  PORTD |= _BV(PD2);
19
  OCR1A = 255;
20
  OCR1B = 0;
21
    
22
  init();
23
  
24

25
  PORTD &= ~_BV(PC7);
26
  
27
  *Dazwischen einige Routinen mit Lesen aus dem Eeprom usw*
28

29
  TCCR0B |= _BV(CS00) | _BV(CS02);
30
  TCCR0A |= _BV(WGM01);
31
  TCCR0A = (1<<WGM01);
32
  OCR0A = 155;
33
    
34
  TIMSK0 = _BV(OCIE0A); // compare interrupt
35

36
  
37
  sei();
38
  uart_puts("Teststring");
39
  
40
  while (1) {}
41
  }
42
}
43
ISR (TIMER0_COMPA_vect) {
44

45
* Hier werden dann Regelungsfunktionen aufgerufen * 
46
  TCNT0 = 0; 
47
}

Der Teststring kommt nicht komplett an. Lib ist übrigens die von Peter 
Fleury.
Gast #1774552
Lesenswert?

Du kannst auch eine Zeitscheibe programmieren.

Beitrag "Genaue Sekunde und Zeitscheibe mit Timer0 erzeugen"


Oder auch am Ende eines jeden Interrupts innerhalb der Interruptroutine 
jeweils ein Zeichen über UART übertragen, falls noch ein Zeichen zur 
Ausgabe vorhanden ist die Zeit noch reicht.

Oder aber deine Interruptroutine so kurz machen und nur Flags setzen, so 
dass die serielle Schnittstelle nur geringfügige Fehler erhält.
Deine IRQ-Aufgaben werden dann außerhalb der IR_Routine erledigt.

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