Forum: Compiler & IDEs uart problem


von Freak (Gast)


Lesenswert?

Hallo,

ich bin relativ neu in der AVR programmierung.
ich sende meine Befehle für den controller (Atmega8515) per USART.
zur zeit besteht ein befehl aus 7 bytes.
Wenn ich jedoch vom pc 2 befehle schnell hintereinander sende, geht
anscheinend alles durcheinander.befehle werden falsch oder garnicht
mehr ausgeführt

folgendes system verwende ich:

uint8_t bytesReceived = 0;
uint8_t receiveBuffer[7];

//Einsprungpunkt der UART Empfangsroutine
ISR(UART_RX_vect) {
  receiveBuffer[bytesReceived] = UDR;
  bytesReceived++;

  if (bytesReceived == 7) {
  ...
  bytesReceived = 0;
  }
}

Die eigentliche abarbeitung der Befehler erfolgt nicht im
empfangsinterrupt. sondern wird von einem timer nebenbei erledigt.
woran kann das liegen?
baudrate ist richtig eingestellt. (vom controller an den PC senden
funktioniert reibungslos...)

was geschiet mit bytes die empfangen werden, während eine interrupt
routine des timers arbeitet? dann scheint der fehler aufzutreten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du brauchst ein Handshake, an Hand dessen der Sender erkennt,
ob der Empfänger überhaupt schon wieder gewillt ist, etwas
entgegenzunehmen.  Andernfalls riskierst du, dass du den
Empfangspuffer mit neuem Kram zuknalls, während der AVR gerade
noch damit beschäftigt ist, die vorherige Aufgabe auszuführen.

von Freak (Gast)


Lesenswert?

daran scheint es nicht zu liegen.
auch wenn ich einige zeit mit dem zweiten befehl warte, kommt es zu den
problemen.
also wenn er daten empfängt während von den Timern etwas ausgeführt
wird.

von Stefan (Gast)


Lesenswert?

In welchem Interruptlevel (Priorität) läuft dein UART und in welchem
dein Timer? Sperrst du in der Timerroutine die Interrupts? Alle (böse)
oder nur per Interruptmaske einige z.B. den Timer (Gut)?

von Günni (Gast)


Lesenswert?

Hallo,

u.U. manipulierst Du den Buffer für den Befehl, bevor er abgearbeitet
wurde.
Du mußt sicherstellen, dass der Befehl abgearbeitet wurde bevor neue
Daten in den Buffer geschrieben werden.
Um Zeit zu gewinnen kannst Du den Buffer bei Vollständigkeit in einen
"Abarbeitungsbuffer" kopieren.

Grüße
Günni

von Freak (Gast)


Lesenswert?

so wie ich es gelesen hab, sorgt der gcc compiler dafür, dass die
interrupts global deaktiviert werden, wenn einer ausgelöst wird, und
nach abschluss der ISR aktgiviert der compiler sie wieder.

von Freak (Gast)


Lesenswert?

es geht eigentlich nur um eine simple schrittmotorsteuerung.
Vielleicht kennt jemand gute quelltexte, wo ich mir das mal angucken
könnten.

m.f.G.
Freak

von johnny.m (Gast)


Lesenswert?

>...sorgt der gcc compiler dafür, dass
>die interrupts global deaktiviert werden...

Das stimmt so nicht ganz. Das globale Interrupt Disable während der
Ausführung einer ISR macht nicht der Compiler, sondern die Hardware des
µC. Die kann man 'überlisten', indem man am Anfang der ISR die
Interrupts wieder freigibt (entweder manuell mit sei() oder durch
Verwendung von __attribute__((interrupt)) anstelle von 'ISR' zum
Einleiten der ISR), was man allerdings nur dann tun sollte, wenn man
sich über die möglichen Folgen im Klaren ist.

Möchte man verhindern, dass ein Interrupt, der während einer bestimmten
Aktion aufgetreten ist, nach Beendigung dieser Aktion nicht bearbeitet
wird, dann genügt es nicht, den Interrupt während der Aktion zu
deaktivieren, sondern man muss, bevor man ihn wieder aktiviert, das
entsprechende Flag löschen. Tut man das nicht, wird der Interrupt
sofort nach der Reaktivierung bearbeitet!

Gruß

Johnny

von johnny.m (Gast)


Lesenswert?

>...sorgt der gcc compiler dafür, dass
>die interrupts global deaktiviert werden...

Das stimmt so nicht ganz. Das globale Interrupt Disable während der
Ausführung einer ISR macht nicht der Compiler, sondern die Hardware des
µC. Die kann man 'überlisten', indem man am Anfang der ISR die
Interrupts wieder freigibt (entweder manuell mit sei() oder durch
Verwendung von __attribute__((interrupt)) anstelle von 'ISR' zum
Einleiten der ISR), was man allerdings nur dann tun sollte, wenn man
sich über die möglichen Folgen im Klaren ist.

Möchte man verhindern, dass ein Interrupt, der während einer bestimmten
Aktion aufgetreten ist, nach Beendigung dieser Aktion bearbeitet wird,
dann genügt es nicht, den Interrupt während der Aktion zu deaktivieren,
sondern man muss, bevor man ihn wieder aktiviert, das entsprechende Flag
löschen. Tut man das nicht, wird der Interrupt sofort nach der
Reaktivierung bearbeitet!

Gruß

Johnny

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.