Forum: Mikrocontroller und Digitale Elektronik UART&Timer Interrupt


von Björn (Gast)


Lesenswert?

Morgen,

kann es sein dass sich der UART-Receive und der Timer-Compare Interrupt
irgendwie gegenseitig behindern?

Beide ISR-Routinen sind ziemlich lang. Macht es Sinn den einen
Interrupt auszuschalten und danach wieder ein, während der andere
läuft?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Beide ISR-Routinen sind ziemlich lang.
Fehler! ISR immer so kurz wie möglich machen.

>Macht es Sinn den einen Interrupt auszuschalten und danach wieder
>ein, während der andere läuft?

Beim AVR ist immer nur eine ISR aktiv. Während ihrer Abarbeitung können
zwar andere Interrupts auftreten, diese werden aber erst noch Beendigung
der ISR bearbeitet.

Verkürz die beiden ISR auf das nötigste, dann hast du auch keine
Probleme mit Überschneidungen.
(USART-Empfang kann man gut in einem Ringpuffer zwischenlagern...)

von tastendrücker (Gast)


Lesenswert?

>Verkürz die beiden ISR auf das nötigste..

Exakt! (Meine) Goldene Regel:
Mache möglicht viel mit, aber möglicht wenig in Interrupts

von Thilo (Gast)


Lesenswert?

Und die Prioritäten der Interrupts beachten, falls mehrere gleichzeitig
aktiv sind!

von Björn (Gast)


Lesenswert?

Ändert sich leider gar nichts.

Das erzeugte Signal ist soweit auch in Ordnung, nur alle 5-10s gibt es
irgendwie nen Ruckler, so ähnlich wie ne Spannungsspitze.

Aber komisch dass es nur alle 5-10s auftritt, obwohl der UART alle 90ms
ausgewertet wird...

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Dann hast du scheinbar ein anderes Problem...

von Björn (Gast)


Lesenswert?

Und was kann das sein?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Zeile 42...(in deinem nicht geposteten Quellcode)

von Björn (Gast)


Angehängte Dateien:

Lesenswert?

Sorry, vergessen!

Hier ist der Code......

von inoffizieller WM-Rahul (Gast)


Lesenswert?

tmp2 = array2;
          for( i = 1; i; i *= 2 )
          *(tmp2++) = (c&i) ? 54 : 35;

        Array_Servo2[3]  = array2[0];
        Array_Servo2[5]  = array2[1];
        Array_Servo2[7]  = array2[2];
        Array_Servo2[9]  = array2[3];
        Array_Servo2[11] = array2[4];
        Array_Servo2[13] = array2[5];
        Array_Servo2[15] = array2[6];
        Array_Servo2[17] = array2[7];

       state = STATE_IDLE;

Den "Klotz" hast du doppelt...

Einfacher wäre es, wenn du ein Feld mit 2 Indizes benutzen würdest:
Array_Servo[2][18]
Dann könntest du in Abhängigkeit des "states" das jeweilige Feld
beschreiben.
Und wenn du ein wenig rechnest, kannst du dir die Hilfsfelder
sparen...

das würde dann so aussehen:
tmp = 3;
for( i = 1; i; i *= 2 )
{
 Array_Servo[ServoNr][tmp] = (c&i) ? 54 : 35;
 tmp += 2;
}
state = STATE_IDLE;

Du kannst dir auch eine Menge Speicherplatz sparen, wenn du nur eine
Hilfsvariable/-Feld benutzt. Es kann ja nicht passieren, dass auf beide
Felder gleichzeitig zugegriffen wird.
Dass man das alles noch etwas weiter verschönern kann, hatte ich ja
irgendwann schon mal erklärt...

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Könntest du bitte noch mal die gesamte Problemstellung aufschreiben?
Es ging irgendwie um die Erzeugung verschiedener Puls-Längen in
Abhängigkeit empfangener Datenbytes, oder?

von Björn (Gast)


Lesenswert?

Genau!

Also,

mit dem Timer Interrupt erzeuge ich mir ein Signal.
Bei diesem Signal (Highpegel ) sollen alle ca. 90ms neun Low-Pegel mit
einer bestimmten Länge erzeugt werden.

Also erst mal 90ms Highpegel, dann ein Lowpegel von 45µs, ein Highpegel
von 120µs, 50µs Low, 120µs High, 50µs Low, 120µs High, 50µs Low, 120µs
High, 50µs Low, 120µs High, 50µs Low, 120µs High, 50µs Low, 120µs High,
50 µs Low, 120 High, 40 µs Low und dann wieder 90ms Pause.

Mit diesem auf den ersten Blick komischen Signal soll ein Servo
angesteuert werden. Kein Standard Servo! Dieser Servo benötigt ein
Start-Bit(hier die 45 µs) und dann 8 weitere Bit für die jeweilige
Stellung. Dabei sind 40µs eine 0, und 50µs eine 1. Heißt also wenn
alle Bits 1 sind ganz nach rechts, wenn alle Bits 0 sind ganz nach
links. Die voreingestellten Werte sind für die Mittelstellung.

Nun soll ein ankommendes Byte über UART so ausgewertet werden, dass
mir die Bits entsprechend gesetzt werden. Funktioniert auch alles
bestens.

Nun benutze ich das STK500 mit einem Atmega88 drauf. AD-Wandler
eingerichtet und den Servo über ein Poti gesteuert. Klappt auch alles
Prima. Servo fährt in alle Positionen und auch ohne diese komischen
Ausschläge alle paar Sekunden.

Das Problem tritt nur auf, wenn ich jetzt zwei STK500 verwende. Das
eine verwende ich als Sender, das andere als Empfänger. Verbunden sind
die beiden über UART. Masse ist auch verbunden. Wenn ich nun mit einem
Poti an einen Board, den Servo am anderen Board steuern will treten
diese komischen Ausschläge des Servos alle paar Sekunden auf. Ansonsten
fährt der Servo aber in die gewünschten Positionen.

Nun weiß ich nicht wie ich diese komischen Ausschläge da weg bekommen
kann.....

von Björn (Gast)


Lesenswert?

Weiß keiner woher das kommen könnte?

von Björn (Gast)


Lesenswert?

Hab es immer noch nicht hinbekommen! ;-(

@Jonny:

Wozu steht denn das temp = 3; in folgenden Teilstück?

tmp = 3;
for( i = 1; i; i *= 2 )
{
 Array_Servo[ServoNr][tmp] = (c&i) ? 54 : 35;
 tmp += 2;
}
state = STATE_IDLE;


Hab das Stück Code was du oben gepostet hast noch nicht ganz kapiert.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Bin zwar nicht Jonny, aber wenn du dir den Verlauf der Schleife
anguckst, stellst du fest, dass das Array ab Eintrag Nummer 3 erst
verändert wird (die Einträge davor sind ja quasi konstant).
Danach werden wird nur jeder 2. Eintrag (die mit ungeradem Index)
verändert.
So kann man sich die Verwendung des Hilfsarrays sparen.
Du solltest das "Programm" einfach mal auf Papier "ablaufen" lassen
und die einzelnen Werte aufschreiben. Das bringt IMHO mehr als wenn man
sich das im Simulator anguckt.

von Björn (Gast)


Lesenswert?

Ah, jetzt hab ich es kapiert! DANKE!

Doch das andere Problem lässt sich einfach nicht lösen! Haste da nicht
auch ne Idee?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Leider nicht.

von Stefan (Gast)


Lesenswert?

Schade, aber trotzdem Danke!

Hab da noch ne Frage...

Du hast mir oben das geschrieben:

tmp = 3;
for( i = 1; i; i *= 2 )
{
 Array_Servo[ServoNr][tmp] = (c&i) ? 54 : 35;
 tmp += 2;
}
state = STATE_IDLE;


müsste es nicht:

*tmp = 3;
for( i = 1; i; i *= 2 )
{
 Array_Servo[ServoNr][*tmp] = (c&i) ? 54 : 35;
 tmp += 2;
}
state = STATE_IDLE;

heißen. Also noch die Sternchen davor?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Nein.
tmp ist einfach nur ein Zähler (Byte-Variable). Natürlich kannst du den
auch als Pointer deklarieren - das kostet aber unnötig Speicherplatz.
Die Deklaration hätte ich vielleicht noch dazuschreiben sollen.

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.