Hallo zusammen,
ich möchte per UART ein Zeichen als String empfangen und je nach Zeichen
einen Pin High oder Low setzen.
Leider funktioniert mein Programm nicht und ich weiß nicht warum.
UART selbst funktioniert, da ich an mein Terminalprogramm testweise
Strings senden konnte.
Wo liegt der Fehler?
Vielen Dank :-)
Dussel schrieb:> Ich gehe jetzt mal von einem ATMega8 aus. Sendest du im 5-Bit Format?> Sonst solltest du im UCRSC auch was ändern.
Schon mal im Datenblatt den Default-Inhalt von UCSRC angeschaut?
Dussel schrieb:> Ich gehe jetzt mal von einem ATMega8 aus. Sendest du im 5-Bit Format?> Sonst solltest du im UCRSC auch was ändern.
Danke für die Antwort :-)
Nein, es war 8-Bit eingestellt und nun habe ich das Terminalprogramm auf
5-Bit eingestellt und es funktioniert auf anhieb.
Vielen Dank :-)
Das mit dem USRC werde ich mal nachlesen :)
R. B. schrieb:> Wo liegt der Fehler?
Was genau wird denn überhaupt gesendet?
Dass der Pin nur sehr kurz Low ist, wenn du im Terminalprogramm A und
danach Return drückst, ist dir klar, oder?
Stefan Ernst schrieb:> Schon mal im Datenblatt den Default-Inhalt von UCSRC angeschaut?
Nein, tatsächlich nicht, aber
> Nein, es war 8-Bit eingestellt und nun habe ich das Terminalprogramm auf> 5-Bit eingestellt und es funktioniert auf anhieb.
?
Was ist denn jetzt los?
Dussel schrieb:> Stefan Ernst schrieb:>> Schon mal im Datenblatt den Default-Inhalt von UCSRC angeschaut?> Nein, tatsächlich nicht, aber>> Nein, es war 8-Bit eingestellt und nun habe ich das Terminalprogramm auf>> 5-Bit eingestellt und es funktioniert auf anhieb.> ?>> Was ist denn jetzt los?
Ich meinte natürlich UCSRC ;-)
Das Sendeformat im Terminalprogramm war falsch eingestellt.
Und das beim nächsten Zeichen alles wieder high ist, ist mir klar!
Ich muss mir noch überlegen, wie ich es hinbekomme, das es low bleibt.
Vielleicht mit einer Switch-Anweisung, mal sehen.
Im Moment geht es nur darum, ein bisschen zu spielen und zu lernen :)
Danke :-)
Dussel schrieb:> Was ist denn jetzt los?
Reines Glück. Wenn 5 Bits gesendet werden, der AVR aber 8 erwartet, wird
anscheinend das A trotzdem noch erkannt, das nachfolgende \r aber
verschluckt, und schon scheint sein Code zu funktionieren.
R. B. schrieb:> Das Sendeformat im Terminalprogramm war falsch eingestellt.
Nein, war es nicht. Dein AVR ist auf 8N1 eingestellt.
R. B. schrieb:> Und das beim nächsten Zeichen alles wieder high ist, ist mir klar!
Aber ist dir auch klar, dass wahrscheinlich(*) sofort ein "nächstes
Zeichen" kommt, und der Pin damit nur ca 1 ms lang low ist?
(*) man kann hier nur mutmaßen, denn du hast die Frage danach, was wie
gesendet wird, ja nicht beantwortet.
Stefan Ernst schrieb:> Dussel schrieb:>> Was ist denn jetzt los?>> Reines Glück. Wenn 5 Bits gesendet werden, der AVR aber 8 erwartet, wird> anscheinend das A trotzdem noch erkannt, das nachfolgende \r aber> verschluckt, und schon scheint sein Code zu funktionieren.
Ich habe gerade alles zum UCRSC nachgelesen und wenn ich da keine Bits
setze, wird doch erwartet, dass ich 5 Bits sende, also passt doch alles,
wenn ich im Terminalprogramm nun 5 Bits sende :)
R. B. schrieb:> Ich habe gerade alles zum UCRSC nachgelesen und wenn ich da keine Bits> setze, wird doch erwartet, dass ich 5 Bits sende
Welcher AVR soll das sein? Ich habe noch keinen gesehen, beim dem der
Inhalt des Registers nach einem Reset 0 ist.
Stefan Ernst schrieb:> R. B. schrieb:>> Ich habe gerade alles zum UCRSC nachgelesen und wenn ich da keine Bits>> setze, wird doch erwartet, dass ich 5 Bits sende>> Welcher AVR soll das sein? Ich habe noch keinen gesehen, beim dem der> Inhalt des Registers nach einem Reset 0 wäre.
Ok... möglicherweise bin ich auf dem Holzweg ;)
Das hier ist ein Atmega 8 und ich dachte bisher, das alle bits
standardmäßig nicht gesetzt seien, aber anscheinend ist dem nicht so :)
Wie müsste man denn dann meinen Code ändern, damit alles in UCRSC
wirklich sicher 0 gesetzt ist? Einfach UCRSC=0x00?
R. B. schrieb:> Das hier ist ein Atmega 8 und ich dachte bisher, das alle bits> standardmäßig nicht gesetzt seien, aber anscheinend ist dem nicht so :)
Im Datenblatt steht bei den Registerbeschreibungen der Default-Inhalt
nach einem Reset dabei.
R. B. schrieb:> Wie müsste man denn dann meinen Code ändern, damit alles in UCRSC> wirklich sicher 0 gesetzt ist? Einfach UCRSC=0x00?
Nö, damit schreibst du eine 0 nach UBRRH. Sagtest du nicht "ich habe
gerade alles zum UCRSC nachgelesen"?
Und warum überhaupt willst du denn jetzt den AVR auf 5-Bit umstellen?
Stell einfach dein Terminalprogramm wieder richtig ein.
Stefan Ernst schrieb:> R. B. schrieb:>> Das hier ist ein Atmega 8 und ich dachte bisher, das alle bits>> standardmäßig nicht gesetzt seien, aber anscheinend ist dem nicht so :)>> Im Datenblatt steht bei den Registerbeschreibungen der Default-Inhalt> nach einem Reset dabei.>> R. B. schrieb:>> Wie müsste man denn dann meinen Code ändern, damit alles in UCRSC>> wirklich sicher 0 gesetzt ist? Einfach UCRSC=0x00?>> Nö, damit schreibst du eine 0 nach UBRRH. Sagtest du nicht "ich habe> gerade alles zum UCRSC nachgelesen"?> Und warum überhaupt willst du denn jetzt den AVR auf 5-Bit umstellen?> Stell einfach dein Terminalprogramm wieder richtig ein.
Ok.... ich habe nicht im Datenblatt, sondern in der UART-Beschreibung
auf dieser Seite hier nachgesehen :)
Das Terminalprogramm steht nun auf 8-Bits und es funktioniert.
Da ich echt ein kompletter Neuling in E-Technik und Programmierung bin,
bitte ich etwas um Nachsicht :)
Ich weiß nicht, warum es vorhin nicht funktioniert hat.
Weil standardmäßig stand es auf 8-Bit, aber ging vorhin nicht.
Keine Ahnung warum!
Und zum Thema richtig speichern habe ich gerade keine elegante Idee.
Wie realisiert man es elegant, wenn man verschiedene Pins low oder high
setzten will und die ihren Status behalten sollen, solange der Status
nicht explizit geändert wird?
Vielen Dank :-)
Leider funktioniert dies auch wieder nicht wie es soll.
Meine Idee ist, dass ich bei dem ersten if ein XOR bräuchte statt einem
normalen Oder. Aber ein richtiges logisches XOR gibt es in C nicht,
oder?
Habe ich mit meiner Vermutung recht oder liegt mein Fehler mal wieder wo
anders? ;-)
Danke! :)
ich versteht gar nicht was du mit der Variabel "erhalt" erreichen
willst. Lass sie einfach weg. Dann geht die LED bei 'A' und bei 'B' aus.
Man darf code übrigens auch auf mehr also eine Zeile schreiben, das ist
dann allgemein besser lesbar.
Peter II schrieb:> ich versteht gar nicht was du mit der Variabel "erhalt" erreichen> willst. Lass sie einfach weg. Dann geht die LED bei 'A' und bei 'B' aus.>> Man darf code übrigens auch auf mehr also eine Zeile schreiben, das ist> dann allgemein besser lesbar.
Das Ziel ist, wenn ich nach dem "A" z.B. ein "X" sende, dass der
Zustand, den A ausgelöst hat, solange bleibt, bis wirklich ein "B"
kommt.
R. B. schrieb:> Das Ziel ist, wenn ich nach dem "A" z.B. ein "X" sende, dass der> Zustand, den A ausgelöst hat, solange bleibt, bis wirklich ein "B"> kommt.
dafür braucht man keine Variable.
Wenn 'A'
Lampe AN
Wenn 'B'
Lampe AUS
wenn weder 'A' noch 'B' kommt, dann ändert sich einfach die lampe nicht.
Stefan Ernst schrieb:> Wenn 5 Bits gesendet werden, der AVR aber 8 erwartet, wird> anscheinend das A trotzdem noch erkannt, das nachfolgende \r aber> verschluckt
Welches \r?
> dass wahrscheinlich(*) sofort ein "nächstes> Zeichen" kommt, und der Pin damit nur ca 1 ms lang low ist?
Zwar wissen wir es nicht explizit, doch sieht alles danach aus, dass der
TO einzelne Zeichen sendet. Von irgendetwas Zeilenorientiertem und den
dazugehörigen Zeilenendzeichen war nun wirklich nie die Rede.
Vorschlag: pack das Lesen von receive_char in main() in einen
interruptsperrenden Block und setze receive_char dort auf 0. Dann
bedeutet receive_char !=0 dass ein neues Zeichen eingetroffen ist.
Zumindest wenn du kein NUL über den UART empfangen möchtest.
Peter II schrieb:> R. B. schrieb:>> Das Ziel ist, wenn ich nach dem "A" z.B. ein "X" sende, dass der>> Zustand, den A ausgelöst hat, solange bleibt, bis wirklich ein "B">> kommt.>> dafür braucht man keine Variable.>> Wenn 'A'> Lampe AN>> Wenn 'B'> Lampe AUS>> wenn weder 'A' noch 'B' kommt, dann ändert sich einfach die lampe nicht.
Tatsächlich....
Ich glaube es ist schon zu spät für mich, um noch klar zu denken ;-)
Malte S. schrieb:> Stefan Ernst schrieb:>> Wenn 5 Bits gesendet werden, der AVR aber 8 erwartet, wird>> anscheinend das A trotzdem noch erkannt, das nachfolgende \r aber>> verschluckt>> Welches \r?>>> dass wahrscheinlich(*) sofort ein "nächstes>> Zeichen" kommt, und der Pin damit nur ca 1 ms lang low ist?>> Zwar wissen wir es nicht explizit, doch sieht alles danach aus, dass der> TO einzelne Zeichen sendet. Von irgendetwas Zeilenorientiertem und den> dazugehörigen Zeilenendzeichen war nun wirklich nie die Rede.>> Vorschlag: pack das Lesen von receive_char in main() in einen> interruptsperrenden Block und setze receive_char dort auf 0. Dann> bedeutet receive_char !=0 dass ein neues Zeichen eingetroffen ist.> Zumindest wenn du kein NUL über den UART empfangen möchtest.
Im Moment sind es einfach nur einzelne Zeichen.
An mehrere Zeichen traue ich mich erstmal nicht ran.
Da durchschaue ich noch nicht, wie das mit dem Interrupt geht, weil ja
pro Interrupt immer nur ein Zeichen abgeholt wird und ich sie dann
irgendwie in einem Array wieder zusammenfügen müsste.
So stelle ich es mir zumindest vor ;)
Da bietet sich ein ring buffer an. Du nimmst ein Array, das z.B. 16 char
groß ist und dazu zwei Indizes: einen Lese- und einen Schreibzeiger. In
der ISR vergleichst du die Zeiger: sind sie identisch, hat du einen
Überlauf, den zu behandeln je nach Anwendung verschieden sinnvoll ist.
Sonst schreibst du das empfangene Zeichen am Schreibzeiger in den Puffer
und erhöhst den Zeiger modulo Puffergröße. In der konsumierenden Routine
vergleichst du auch die Zeiger, ist der Leseindex eins hinter dem
Schreibindex (mod Größe), ist der Puffer leer. Ansonsten liest du am
Leseindex und erhöhst diesen mod Größe.
Ist der Puffer groß genug, kannst du ihn auch direkt nehmen, um z.B.
eine ganze Befehlszeile darin zu speichern (nur immer an den Umbruch
denken).
Sorry für die Prosa, macht sich am Handy besser als Code reinzutouchen.
dann spielt es keine Rolle, ob du in deinem Terminal-Programm vergisst
oder nicht vergisst, die Shift-Taste zu drücken um dann auch wirklich
ein großes 'A' oder 'B' zu senden.
Und es ist auch meistens eine ziemlich gute Idee, wenn man das
empfangene Zeichen wieder an den Sender zurückschickt, damit der eine
Rückmeldung hat, was er eigentlich gedrückt hat.
Malte S. schrieb:> Stefan Ernst schrieb:>> Wenn 5 Bits gesendet werden, der AVR aber 8 erwartet, wird>> anscheinend das A trotzdem noch erkannt, das nachfolgende \r aber>> verschluckt>> Welches \r?>>> dass wahrscheinlich(*) sofort ein "nächstes>> Zeichen" kommt, und der Pin damit nur ca 1 ms lang low ist?>> Zwar wissen wir es nicht explizit, doch sieht alles danach aus, dass der> TO einzelne Zeichen sendet.
Ja, jetzt, aber nicht nach den ersten Beiträgen.
> Von irgendetwas Zeilenorientiertem und den> dazugehörigen Zeilenendzeichen war nun wirklich nie die Rede.
Davon, was er wie sendet, war GAR NICHT nicht die Rede. Es hieß nur
"funktioniert nicht", ohne dass ich ein Problem im Code sah. Die
Annahme, dass er in ein x-beliebiges Terminalprogramm A tippt, und dann
Return drückt, und damit sein "funktioniert nicht" lediglich ein "der
Pin ist so kurz low, dass ich es nicht mitbekomme" ist, ist ja nun nicht
soo weit hergeholt, oder?
Könnt ihr bitte den Blödsinn bleiben lassen?
Es kommt doch nun wirklich jeden Tag x-fach vor, dass gerade Neulinge
maximal die Hälfte (meistens noch viel weniger) von dem erzählen was
eigentlich wichtig ist.
Die Hypothese, dass er 'A' - <Return> tippt ist genausowenig von der
Hand zu weisen, wie die Hypothese, dass er es nicht tut. Bei Neulingen
würde ich erst mal nichts, aber auch gar nichts, von vorne herein
aussschliessen. Und das inkludiert auch unbeabsichtigte Fehlbedienung.
Klar ist das nicht von der Hand zu weisen, aber
R. B. schrieb:> Und das beim nächsten Zeichen alles wieder high ist, ist mir klar!
sprach m.E. doch eher dagegen, sich darauf als Ursache so festzulegen.
Nur gegen das Festlegen, nicht die grundsätzliche Option.
Vielen Dank an alle für die super Hilfe.
Ich finde es besser, wenn man bei Anfängern auch ein bisschen mehr
zwischen den Zeilen liest ;-)
Es war nur ein A ohne Return ;-)
Und der Tipp kleine und große Buchstaben als Eingabe für eine Aktion zu
nehmen ist auch super :)