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
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.
Hallo Karl-Heinz, Ich würde diese Werte auch nur 1x pro Sekunde rausgeben wollen. Es ist übrigens umgekehrt, das senden der Zeichen wird von der Regelung unterbrochen (und macht danach auch nicht weiter ..)
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.
> Es ist übrigens umgekehrt, das senden der Zeichen wird von der > Regelung unterbrochen (und macht danach auch nicht weiter ..) Zeig mal. Das klingt nach einem Designflaw.
Hallo David, dann debugge bitte Dein Programm. Das von Dir beschriebene Verhalten deutet auf Designfehler bzw Programmfehler hin. Meine Glaskugel sagt: Zeile 42. Bernhard Edit: Da war wer schneller.
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.
:
Bearbeitet durch Admin
Interruptroutinen sollte man immer so kurz wie möglich machen. Nur das machen, was sofort passieren muss, dann ein Flag setzen, damit die Hauptschleife weiß, dass es neue Daten zum Verarbeiten gibt.
Müsste er nicht wenigstens nach dem Timer-Interrupt zurückspringen und die fehlenden Zeichen ausgeben?
David P. schrieb: > Müsste er nicht wenigstens nach dem Timer-Interrupt zurückspringen und > die fehlenden Zeichen ausgeben? Müsste er und tut er im Normalfall auch. Irgendwas hast du da verbockt.
Was ich mir zb vorstellen könnte: Dass deine Reglungsfunktionen viel zu lange brauchen. Dadurch steckt der µC praktisch nur noch in der Regelung und für das Drumherum bleibt keine Zeit mehr übrig.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.