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?
>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...)
>Verkürz die beiden ISR auf das nötigste..
Exakt! (Meine) Goldene Regel:
Mache möglicht viel mit, aber möglicht wenig in Interrupts
Und die Prioritäten der Interrupts beachten, falls mehrere gleichzeitig aktiv sind!
Ä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...
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...
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?
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.....
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.
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.
Ah, jetzt hab ich es kapiert! DANKE! Doch das andere Problem lässt sich einfach nicht lösen! Haste da nicht auch ne Idee?
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.