Forum: Mikrocontroller und Digitale Elektronik Keine Buchstaben, aber Zahlen auf HD44780, UART, ATtiny2313


von M. P. (phpmysqlfreak)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich habe ein Problem mit einem meiner kleinen Projekte:

*Zielsetzung:*
Ansteuerung eines HD44780-Displays
Daten und Befehle werden über UART entgegen genommen
 => ("C" gefolgt von Kommando, "D" gefolgt von Daten)

*Randbedingungen:*
9600 Baud, 8 Datenbits, 1 Stoppbit, keine Parität
Interner Takt, 1MHz
=> Ja, mir ist die Ungenauigkeit des internen Quarzes bekannt! Siehe 
"Was funktioniert nicht:"

*Hardware:*
Aufbau auf Steckbrett, mySmartUSB MK2 als UART-Bridge

*Was funkioniert:*
LCD-Initialisierung, (testweise) angezeigter Text, sekündlich 
abwechselnder Text (_delay_ms(1000) passt)
Anzeige der Ziffern 0 bis 9 und "!"

*Was funktioniert nicht:*
Anzeige anderer eingehender Zeichen aus UDR
 => und dadurch funktioniert auch die Abfrage von "C" und "D" nicht

Mein Oszi zeigt mir, was ich erwarte:
104µs Bitzeit, Startbit, 8 Datenbits, Stoppbit. Alles entsprechend der 
gesendeten Bytes. - Dazu verwende ich "putty" unter Windows sowie 
"screen" unter Debian Stable.

In der angehängten ZIP ist das komplette Projekt zu finden.
Ich vermute den Fehler allerdings entweder in der State-Machine oder 
einer falschen UART-Konfiguration. Ich bin zur Zeit etwas überfragt, was 
den Fehler angeht, und hoffe, dass mir hier jemand helfen kann, oder mal 
nen Baumstamm nimmt und auf den Fehler zeigt. ;)
Ich hoffe, der Code ist verständlich und ausreichend kommentiert.


Vielen Dank schonmal im vorraus.

von Volker (Gast)


Lesenswert?

>Ich vermute den Fehler allerdings entweder in der State-Machine oder
>einer falschen UART-Konfiguration.

Warum schreibst du dir dann nicht einfach ein Minimal-Programm ohne 
State-Machine?

Also in der Hauptschleife nur auf die USART warten und dann sofort auf 
LCD ausgeben?

von spontan (Gast)


Lesenswert?

Noch einfacher zum Testen:

Gibt doch mal einen String auf das Display aus. Vielleicht hast Du da 
was nicht so ganz verstanden.

Wenn das klappt, dann UART -> LCD.

von M. P. (phpmysqlfreak)


Lesenswert?

spontan schrieb:
> Gibt doch mal einen String auf das Display aus. Vielleicht hast Du da
> was nicht so ganz verstanden.

Das klappt seit Jahren - und ich habe es auch schon in diesem Projekt 
erfolgreich getestet. - Steht ja unter "Was funktioniert:" ;)


Volker schrieb:
> Also in der Hauptschleife nur auf die USART warten und dann sofort auf
> LCD ausgeben?

Das wird der nächste Schritt sein. Danke für den Tipp.

von chris (Gast)


Lesenswert?

schau dir doch mal das hier an:
Beitrag "LCD über nur einen IO-Pin ansteuern"

von M. P. (phpmysqlfreak)


Lesenswert?

chris schrieb:
> schau dir doch mal das hier an:
> Beitrag "LCD über nur einen IO-Pin ansteuern"

Das Projekt ist mir durchaus bekannt, jedoch geht es mir in erster Linie 
um den Lerneffekt und nicht um das bloße einsetzen eines 
Programmausschnitts.
Von den Leuten gibt es ja leider zu viele. - Ist aber zu OT.

Wo verstecken sich solche Fehler und wie wird etwas am besten umgesetzt? 
- Das ist das, was ich wissen möchte. :)

von M. P. (phpmysqlfreak)


Lesenswert?

Hallo nochmal,

ich habe jetzt mal ein Minimal-Programm aufgespielt:
1
  while(1)
2
  {
3
    while((UCSRA & (1 << RXC)) != (1 << RXC));
4
    lcd_data(UDR);
5
  }

Das Ergebnis ist leider dasselbe, wie initial von mir beschrieben.

Ein Tastendruck auf "a" lässt auf dem Display die Zeichenfolge "$?" 
erscheinen. Das "b" sorgt für "!?". Die Ziffern 0-9 sowie ! und " werden 
ebenfalls korrekt angezeigt.

Das Oszi gibt mir mit Start- und Stoppbit:
Bitfolge für "a": L H L L L L H H L H / Hex: 0x61 / ASCII: a
Bitfolge für "b": L L H L L L H H L H / Hex: 0x62 / ASCII: b
Bitfolge für "1": L H L L L H H L L H / Hex: 0x31 / ASCII: 1




EDIT:
Ok, Kommando zurück. Ich habe den Fehler ausfindig machen können. - 50cm 
vor dem Bildschirm hat jemand vergessen, dass UCSRC:0 für die Polarität 
ist. - Der jenige nahm fälschlicherweise an, die Bits 1:0 seien UCSZ1 
und UCSZ0...

von R. F. (rfr)


Lesenswert?

Hmmm
schwerwiegender Fehler in OSI-Ebene 8.

:-)

von Rc (Gast)


Lesenswert?

Hast du schonmal die 1MHz nachgemessen (Clock per Fuses am 
entsprechendem Pin ausgeben)? Die kann ohne Abstimmung richtig weit 
danebenliegen.

von Christian K. (the_kirsch)


Lesenswert?

Ich würde dir empfehlen, in deiner UART-ISR einen Ringpuffer zu 
benutzen, damit du mehr Zeichen puffern kannst. Momentan speicherst du 
nur ein Zeichen. Ist deine Main zu langsam können so Zeichen verloren 
gehen.

Ich nehme meistens als Puffer 80 Byte, es seiden ist gibt einen Grund 
RAM zu sparen.

von Jochen S. (jochen_s)


Lesenswert?

Hallo Marcel,

Wie Du oben schon beschrieben hast, nutzt Du den internen Takt. Dieser 
ist recht ungenau und von vielen Parametern abhängig.

Das Du auf dem Oszi alles richtig siehst, ist nicht verwunderlich, da 
hier das Timing auf der PC Seite gemacht wird. Da er der Sender ist. Wer 
aber sagt Dir, dass der MC seine Abtastung richtig durchführt?

Ich würde dennoch mal im Bereich Timing/Takt suchen.

Alternativ mal was vom MC senden lassen, dann sieht man dessen Timing.

Gruß
Jochen

von Karl H. (kbuchegg)


Lesenswert?

Marcel Papst schrieb:

> Wo verstecken sich solche Fehler und wie wird etwas am besten umgesetzt?
> - Das ist das, was ich wissen möchte. :)

Fang erst mal an, derartige Schreibweisen
1
void mcuinit(void)
2
{
3
  // UART initialisieren
4
  UCSRA = 0x02;    //  doppelte übertragungsgeschwindigkeit
5
  UCSRB = 0x90;    //  empänger aktivieren, empänger-interrupt
6
  UCSRC = 0x03;    //  asynchron, keine Parität, 1 stop-bit, 8 daten-bit
7
  UBRRH = 0x00;    //  wird nicht gebraucht, da cpu langsam
8
  UBRRL = 12;      //  9600 Baud bei U2X=1, 0.2% fehler
zu meiden wie der Teufel das Weihwasser. Damit hast du dann schnon viel 
gewonnen. Atmel hat den Bits Namen gegeben und die sollst du auch 
benutzen. Dann wird dein Code lesbarer und Fehler fallen hier leichter 
auf als wie wenn man erst mal die Bits auseinander dröseln muss.

>  jedoch geht es mir in erster Linie um den Lerneffekt

Noble Einstellung. Jedoch kann man sich von anderen auch abschauen, wie 
die ihren Code gestalten, so dass er leichter verständlich, lesbarer und 
damit weniger fehleranfällig wird. Der Unterschied zwischen guten 
Programmiereren und miesen Programmierern besteht nicht nur darin, dass 
die ersteren ihre Sprache beherrschen und zig Algorithmen im Kopf haben. 
Gute Programmierer schaffen es auch mühelos einen Code so zu schreiben, 
dass man ihn in ein paar Sekunden erfassen und verstehen kann. Miese 
Programmierer hingegen schmeissen einem beim Codelesen Prügel zwischen 
die Beine. Motto "Es war schwer zu schreiben, also soll es auch schwer 
zu lesen sein. Und der COmpiler soll mir überhaupt nicht helfen. WO 
kommen wir denn da hin, wenn der Compiler für mich aus Taktfrequenz und 
Baudrate die Konstante für das UBRR ausrechnen würde? Das wär doch viel 
zu einfach, wenn man einen derartigen Parameter simpel ändern könnte. 
Nein! Das muss möglichst kryptisch und schwer zu kontrollieren sein. Das 
sichert meinen Arbeitsplatz!"

von Marcel Papst (als Gast^^) (Gast)


Lesenswert?

Marcel Papst schrieb:
> EDIT:
> Ok, Kommando zurück. Ich habe den Fehler ausfindig machen können. - 50cm
> vor dem Bildschirm hat jemand vergessen, dass UCSRC:0 für die Polarität
> ist. - Der jenige nahm fälschlicherweise an, die Bits 1:0 seien UCSZ1
> und UCSZ0...


Hier nochmal mein Edit von gestern Abend. ;)


Alle anderen Tipps werde ich in Zukunft beachten, vielen Dank dafür.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Karl Heinz schrieb:
> zu lesen sein. Und der COmpiler soll mir überhaupt nicht helfen. WO
> kommen wir denn da hin, wenn der Compiler für mich aus Taktfrequenz und
> Baudrate die Konstante für das UBRR ausrechnen würde? Das wär doch viel
> zu einfach, wenn man einen derartigen Parameter simpel ändern könnte.
> Nein! Das muss möglichst kryptisch und schwer zu kontrollieren sein. Das
> sichert meinen Arbeitsplatz!"

 Zusammenhängende Codeteile ordentlich auseinanderlegen, Kommentare
 löschen oder erst gar nicht schreiben, möglichst oft vor- und
 zurückspringen, versuchen, gar keine Konstanten zu deklarieren,
 Variablen und Routinen möglichst kryptische, sinnlose und überlange
 Namen geben, die sich (wenn irgendwie machbar) möglichst nur in einem
 Buchstaben voneinander unterscheiden, hilft auch ungemein.

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.