Forum: Mikrocontroller und Digitale Elektronik UART Probleme bei Rx/TX Interrupt


von Tobi88 (Gast)


Angehängte Dateien:

Lesenswert?

Guten abend ich habe Probleme mit meiner UART

Ich habe ein Programm auf einem Atmega8 mit 1000000Mhz laufen und einer 
Baudrate von 4800.

Ich sende dann hex zahlen an den Atemga8 mit Hterm bzw realterm. Diese 
zahlen empfange ich per Interrupt auif dem Atmega8 und verarbeite sie in 
der ISR  mit eienr Statemaschiene (die ich hier nicht öffentlich zeigen 
will, ichmache dort allerdings nichts aufregendes ausser die Globale 
Variable ProtocolStM_u8 zu setzen und das selbe mit den errorbits.)
Mit jedem empfangegen Byte schicke ich als response 3 byte zurueck .
Den   aktuellen Zustand, ein leerzeichen (0x20) und die Errorbits.

Mein Problem ist wenn ich den ganzen hex string (10 Byte ) auf einmal 
schicke, bekomme ich nur 7 responde also (21Byte) zurueck

Schicke ich aber zuerst die ersten 5 Byte des hex Strings  und dann die 
zweiten 5Byte bekomme ich  2 mal 5 Responde zurueck.

Im Incorrect Screenshot is nur die 2Hälfte des hexStrings zu sehen. Die 
erste hatte ich aber auch geschickt!

ich tippe auf ein Timing Problem dass die ISR mit dem senden der reponse 
Byte zulange braucht und deshalb ankommende Bytes verschluckt...habt ihr 
eine Idee?

von Svenska (Gast)


Lesenswert?

Du rufst aus deiner Empfangs-ISR die Funktion USART_Transmit auf, die 
wartet(!), bis das Byte auch versendet wurde. Während einer ISR sind 
Interrupts deaktiviert, darum gehen die anderen auch verloren.

Schalte den Sendeinterrupt ein und immer, wenn ein Byte fertig 
übertragen wurde (der Interrupt feuert), startest du die Übertragung des 
nächsten Bytes. Kann sein, dass du dir dafür einen kleinen Ringpuffer 
o.ä. basteln musst.

von holger (Gast)


Lesenswert?

>ich tippe auf ein Timing Problem dass die ISR mit dem senden der reponse
>Byte zulange braucht und deshalb ankommende Bytes verschluckt...habt ihr
>eine Idee?

Natürlich werden Bytes verschluckt wenn deine Response länger
dauert als ein Byte zu empfangen. Es ist also Schwachsinn was
du da machst. Denk dir was anderes aus.

von Tobi88 (Gast)


Lesenswert?

Danke  erstmal für die Antworten... aber das kuriose ist ja dass ich 
überhaupt was empfange und raussende... und das immerhin zu 7 
response.... müsste dann eig garnichts funktionieren?

von c-hater (Gast)


Lesenswert?

Tobi88 schrieb:

> Ich habe ein Programm auf einem Atmega8 mit 1000000Mhz laufen

Wo zum Teufel hast du einen derart schnellen AVR aufgetrieben? Meine 
strecken allesamt allerspätestens bei 26..27MHz die Waffen...

> verarbeite sie in
> der ISR  mit eienr Statemaschiene (die ich hier nicht öffentlich zeigen
> will

Dann ist sie wohl so Scheiße, daß es dir hinreichend peinlich ist. Also 
verbessere sie soweit, bis du sie veröffentlichen kannst. Mit ein bissel 
Glück ist eine Veröffentlichung dann garnicht mehr nötig, weil du den 
Fehler bereits gefunden hast...

von Karl H. (kbuchegg)


Lesenswert?

Tobi88 schrieb:
> Danke  erstmal für die Antworten... aber das kuriose ist ja dass ich
> überhaupt was empfange und raussende... und das immerhin zu 7
> response.... müsste dann eig garnichts funktionieren?

Dein AVR kann EIN Zeichen buffern.
D.h. während du das erste Zeichen verarbeitest, kann das 2.te Zeichen in 
die UART reinkommen.
Aber: Auch dieses muss verarbeitet werden. Während das passiert, kann 
das 2. Zeichen in die UART eingetaktet werden. Aber! Die Zeit, die dafür 
zur Verfügung steht ist jetzt bereits kürzer als beim allerersten 
Zeichen. Denn das allererste Zeichen wurde ja sofort nach seinem 
Eintreffen bearbeitet. Das 2.te Zeichen musste schon ein wenig warten.
Das 3. Zeichen muss noch länger warten.
Und irgendwann reicht das dann eben nicht mehr und ein Zeichen wird in 
der UART überscchrieben, weil der Bufferplatz von einem zeichen dann 
eben nicht mehr ausreicht.

Hol dir vom Peter Fleury die UART Library. Die hat wenigstens eine 
sinnvolle UART Interrupt-Steuerung samt Ringbuffer.

von Patrick B. (p51d)


Lesenswert?

Also mir wurde beigebracht, dass die ISR immer so kurz und schnell wie 
möglich sein sollen -> in deinem Fall das empfangene Byte in einen 
Ring-buffer schreiben und im main dann auf einen Index abfragen ob ein 
unverarbeitetes Byte vorhanden ist. Dann spielts auch keine Rolle, wenn 
mehrere Bytes gepuffer werden.

Anhand der Baudrate kann man errechnen dass alle ~2ms ein neues Zeichen 
ankommt, und da du deine Empfangs-ISR über die UART_Transmitt Funktion 
ausbremst, wird das nie etwas. Obwohl die 2ms eigentlich locker reichen 
sollten für eine riesige State-Machine (deren Sinn und Zweck mehr als 
fragwürdig ist).

von Ingo (Gast)


Lesenswert?

Ein Mega8 @ 1THz, und Intel und co Krebsen noch bei der 5GHz Marke 
rum...

von Tobi88 (Gast)


Lesenswert?

Mit der Peter Fleury Lib geht es dann is die Datei zwar 200byte größer 
aber mal schaun was ich von mir da noch weg optimieren kann

von Amateur (Gast)


Lesenswert?

Da mir die 1000000Mhz ohne Stickstoffkühlung etwas zu hoch erscheinen, 
könnte es sein, dass 1MHz bzw. 1000000Hz gemeint war?

Und wenn ja stellt sich mir allerdings die Frage: Warum fährst Du mit 
angezogener Handbremse? Ein bissel (viel) was schneller kann der ATMega8 
schon. Oder ist das auch geheim?

von Tobi88 (Gast)


Lesenswert?

Als Nick "Amateur" verwenden und dann über einen Tippfehler lustig 
machen.
Aber ich habe schon gemerkt, dass es hier im Forum einige Leute gibt die 
sich über öffensichtliche Tippfehler amüsieren aber keinerlei 
produktiven Beitrag leisten....

Lieber Amatuer jetzt auch für dich ja es waren 1Mhz gemeint!....und ja 
ich könnte ihn auch mit 12Mhz oder mit16 Mhz betreiben. Allerdings 
möchte ich den Atmega8 mit einem Akku betreiben und ggf auf den Atmega8L 
bzw. Atmega8A ausweichen. GGF auch auf die entsprechenden Gegenstücke 
vom Atmega88.
Dort ist der Stromverbrauch bzw. die minimale Versorgungsspannung 
abhängig vom Takt.

P.S. über einen Attiny habe ich auch schon nachgedacht, allerdings 
kommen diese derzeit nicht in Betracht da ich noch diverse Funktionen 
implementieren möchte die verschiedene HW-Komponenten erfordern


Allerdings möchte ich mich herzlich bei Karl Heinz und bei Svenska 
bedanken da ihre Antworten mir geholfen haben mein Problem zu lösen.

von oldmax (Gast)


Lesenswert?

Hi
Nur mal kurz... Warum regst du dich über den hinweis von 1 THz auf? Es 
ist nicht unerheblich, welche Taktfrequenz und welche Baudrate. Außerdem 
läßt 1 MHz die Vermutung zu, das du mit dem internen Takt und ohne Quarz 
arbeitest. Das wiederum ist arg Fehlerbehaftet, weil der interne Takt 
nicht stabil ist. Es ist also immer anzuraten, mit einem ext. Quarz die 
Schaltung zu bestücken, wenn an Datenkommunikation gedacht wird.
Da ich nicht in C programmiere, aber die Vorgehensweise in jeder Sprache 
gleich sein sollte, ja, der Hinweis mit einem Ringpuffer ist richtig. 
Dafür brauchst du 2 Adresszeiger. Einen für den Schreibvorgang, wenn ein 
Empfangsinterrupt auftritt und einen zum Lesen in deiner 
Programmschleife. Am Anfang sind beide Adresszeiger gleich. Kommt ein 
Zeichen, dann wird idie adressierte Speicherzelle beschrieben und der 
Schreibzeiger erhöht. Hat er die Grenze überschritten, wird er wieder 
auf den Anfang gesetzt. In der Programmschleife vergleichst du einfach 
Schreib- und Lesezeiger. Sind sie unterschiedlich, dann ist ein Zeichen 
eingetroffen und du kopierst es entweder in einen Arbeitspuffer oder was 
auch immer. Dann erhöhst du den Lesezeiger und so Gott will, sind Lese - 
und Schreibzeiger wieder gleich. Wenn nicht, wird der Vorgang 
entsprechend fortgesetzt. Beim Überschreiten der Ringpuffergrenze 
natürlich wird auch der Lesezeiger zurückgesetzt. Dadurch bleibt die ISR 
klein und es gehen keine Zeichen verloren.
Gruß oldmax

von Tobi88 (Gast)


Lesenswert?

@oldmax ich rege mich einfach darueber auf weil er nichts produktiv dazu 
beigetragen.

Danke fuer den hinweiss mit dem ringpuffer, aber.mit der lib (s.o) geht 
es jetzt.

Was die sache mit dem internen takt angeht bin ich.mir bewusst dass 
dieser ungenau is..allerdings betraegt bei einer Baudrate von 4800 und 
einem 1Mhz takt der Fehler nur 0.2%.....ich haette nich erwaertet dass 
die Ungenauigkeit des Taktes einen Fehler verursacht der groesser als 
die akzeptablen 2% sind.

von Karl H. (kbuchegg)


Lesenswert?

Tobi88 schrieb:

> dieser ungenau is..allerdings betraegt bei einer Baudrate von 4800 und
> einem 1Mhz takt der Fehler nur 0.2%.....

Das ist in diesem Zusammenhang die falsche Fragestellung.
Die richtige Fragestellung lautet: Habe ich überhaupt 1Mhz? Oder sind es 
eher 0.9Mhz oder doch mehr oder weniger 1.1Mhz? Oder irgendwas 
dazwischen. Oder mit noch mehr Abweichung? Oder wie oder was? Und wie 
ist das, wenn es wärmer wird? Wenn es kälter wird?

von oldmax (Gast)


Lesenswert?

Hi
>ich rege mich einfach darueber auf weil er nichts produktiv
>dazu beigetragen.


So ist das nun mal in einem Forum. Hier sitzen keine bezahlten 
Mitarbeiter einer Hotline, deren Auskünfte selbstverständlich auch 
kostenpflichtig sind. Du befindest dich in einem Forum. Alles was hier 
geschrieben wird, ob eine Antwort zur Frage oder aber nur "wertlose" 
Hinweise hat mehr oder weniger eine Berechtigung. Darüber solltest du 
dir im Klaren sein. Dies ist nicht ein Selbstbedienungsladen, wo man 
Wissen abstauben kann und manchmal gibt es da etwas genervte 
Forenteilnehmer, deren Ton dann nicht immer freundlich bleibt, wenn ein 
Fragesteller glabt, alles muß ihm dienlich sein. Wir wollen auch ein 
wenig Spaß dabei haben.
Ich hoffe, die Antwort von KHB hast du verstanden. Nimm einen externen 
quarzgenauen Taktgeber von 1 MHz und deine Rechnung stimmt. Die interne 
Frequenz ist aber nicht stabill und driftet etwas. Da hilft auch kein 
Kalibrieren, da der interne Takt auch noch temperaturabhängig ist.
Also, nicht überall, wo 1 MHz draufsteht ist auch 1 MHz drin.
Gruß oldmax

von Tobi88 (Gast)


Lesenswert?

@ oldmax
Ok oldmax entschuldigung das wusste ich wenn ich nicht hier was fuer das 
Forum bezahle ich mir bloede Kommentare gefallen muss.....

Ja ich hab KHB verstanden aber wie gesagt nich erwartet dass der Takt 
soweit wegdriftet, dass ich mit meiner 4800Baudrate ueber die 2 % Fehler 
quote komme. Im mom funktioniert es ganz gut mit der lib von.peter 
Fluery und meinen 4800. Trotzdem werde ich den Tipp annehmen und 
sicherheitshalber einen 1Mhz bzw 2Mhz Quarz bzw. Ozillator anschliessen. 
Wo finde ich Infos wie ich die entsprechenden Kondensatoren 
dimensionieren muss? Bei 12 Mhz nehm ich 22p aber die kann ich ja bei 
1Mhz bzw 2Mhz nich nehmen oder?

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.