www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD an AT89S8252 Ansteuerung in C


Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, auch!
Ich bräuchte mal Hilfe von den Profis hier, da ich auch nach Google und
Forensuche keine Lösung für mein Bescheidenes Problem finden kann... Ich
habe eine Standard 2x16-Display (Hd44780 o.ä.) an einem AT89S8252 im
8-Bit-Modus im betrieb. Mit Assembler läuft das auch alles wunderbar,
nur in C haperts halt. Hat jmd. zufällig einen Lauffähigen C-Code zur
init. und evtl. noch ein Ausgabebeispiel für Textstrings. Am liebsten
natürlich für den 89s8252. Besten Dank schonmal! Gerne auch direkt an:
bayluga@freenet.de

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist das Problem?
Setz doch einfach dein ASM-Code in C um...
Fertigen Code wirst du kaum finden, ohne ihn auf dein System anpassen
zu müssen.

Poste doch einfach mal deinen ASM-Code, und was du in C draus gemacht
hast, dann kann dir geholfen werden.

Ralf

Autor: Thomas H. (bayluga)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Puh, habs dann doch irgendwie geschafft, dass der Apparat irgendwas
anzeigt : ) Habe es jetzt jahre ohne C geschafft, aber wenns halt
komplizierter wird, kommt man mit .asm dann doch nicht mehr so weit.
Ich hab mal den src soweit angehängt und hätte da noch ne Frage oder
zwei an Ralf (und wer auch immer das noch liest):

- Warum wird das erste Zeichen des Textstrings nicht angezeigt?

und

- Wie krieg ichs hin, einen Dezimalwert auszugeben? (z.B. 4stellig)

Konnte für beides keinen Beispielcode finden.

Vielen Dank, Kollegen: )

Thomas.

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...Habe es jetzt jahre ohne C geschafft, aber wenns halt
komplizierter wird, kommt man mit .asm...

Mal rein interesse halber, was geht in ASM nicht ?

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gehen tut natürlich alles. Die Frage ist nur, ob man den Überblick
behält. Aber glaub mir, ich bin der ALLERLETZTE, der Assembler nicht zu
schätzen wüsste : )

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Thomas,

sorry für die späte Rückmeldung.
Zu deinen beiden Problemen:

1. Zeichen fehlt:
Führe doch bitte mal den printf-Befehl zweimal hintereinander aus und
sag Bescheid, ob das erste Zeichen immer noch fehlt.

2. Dezimalzahl ausgeben:
Ich gebe jetzt mal folgendes vor:
- Vierstellige Dezimalzahl heisst, der an die C-Funktion übergebene
Parameter ist ein INT. Also sind maximal 5 Stellen möglich.
Der zweite Parameter gibt die Position an. Du musst jetzt folgendes
machen:
1. Stelle = Zehntausender
Du teilst den int durch zehntausend. Das Ergebnis gibst du auf dem
Display aus. Ist das Ergebnis 0, so gibst du anstatt einer Zahl ein
Leerzeichen aus. Du musst dir merken, ob du eine Zahl oder ein
Leerzeichen ausgegeben hast, damit die nächste Stelle korrekt angezeigt
wird (Tausender), wenn das Teilen dort eine Null ergibt.
Damit sorgst du für eine Unterdrückung der Vorlauf-Nullen.
Und das Schema geht bis hin zu den Einern.

Ich hoffe, ich konnte es verständlich beschreiben.

Bitte um Rückmeldung.

Ralf

Autor: Thomas H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Ralf!
Vielen Dank für Deine Antwort. Tja, also das mit dem fehlenden Zeichen
hat sich erledigt. Und um ganz ehrlich zu sein, hab ich das mit der
Teilerei nicht wirklich verstanden. Kann mann das nicht über modulo
machen? Das "Fehlende Zeichen" war übrigens ein
Cursorsteuerungsproblem. Das Display ist ein 2x16 mit HD44780
(standard) und laut datenblatt hat zeile 1 die adressen 00h bis 0Fh
und zeile zwei geht von 40h bis 4Fh. Ich hab zur Cursorpositionierung
eine Funktion geschrieben, die nicht funktioniert, bzw. funktioniert
sie nur für die 2te Zeile, wenn man statt 40h einfach C0h nimmt. Das
soll einer verstehen. Ich häng den Funktionscode einfach mal an,
vielleicht fällt Dir was dazu ein. Hatte das gleiche Phönomen auch
schon in assembler. Eigentlich ist mir ja egal, ob die 2te zeile jetzt
40h oder C0h "heisst", nur kann ich halt z.b. das 3te zeichen der
1ten zeile ansprechen. Idee dazu? Solange beschäftige ich mal mit der
Teilerei.
Vielen Dank schonmal!

Thomas

Autor: Thomas H (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso.. hier die Cursorfunktion : )

void move (int cline, int crow)  // Funktion für Cursorbewegung
{             // move (zeile 1...2, Zeichen 1...16)
    char pos;
    if(cline==1) pos=0x00;
    if(cline==2) pos=0x40;
     pos=pos+crow-1;
    RS=0;RW=0;P2=pos;EN=1;EN=0;
     busychk();
     RS=1;
}

Autor: Ralf Altmann (warpnine)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, bezüglich der Sache mit 0x40 und 0xC0, ich hab jetzt leider keine
Zeit, deinen Code zu prüfen, aber vielleicht komm ich am Wochenende
dazu. Allerdings hab ich zwei Links gefunden, die evtl. weiterhelfen
können:

http://ouwehand.net/~peter/lcd/lcd.shtml
http://www.8052.com/tutlcd.phtml

Wegen der Teilerei:

Ja, das was ich geschrieben habe, ist doch MODULO:
Durch 10000 teilen, das Ergebnis wird ausgegeben, wenn es ungleich 0
ist, ansonsten ein Leerzeichen.
Das mit 10000 multiplizierte Ergebnis des Modulo ziehst du von deinem
Wert ab.
Dann kommt genau die gleiche Sache mit den 1000ern, dann die 100er,
usw.

Ralf

Autor: Thomas H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank für die Links, Ralf. Nach dem Tutorial auf 8052.com müsste
mein Code eigentlich laufen. Obere Zeile also 0x80...0x8F und untere
0xC0...0xCF, aber leider gehts trotzdem nur in der unteren... Wäre
super, wenn Du am WE kurz Zeit dafür fändest. Kannst mir das gerne auch
per mail senden, falls der Thread für "Könner" zu langweilig wird.
bayluga@freenet.de

Grütze,

Thomaas

Autor: Ralf Altmann (warpnine)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, ich guck mal was ich hinkrieg.

Übrigens, kleine Korrektur:

> Ja, das was ich geschrieben habe, ist doch MODULO:
Das ist nicht ganz richtig, ich hab in der Eile Müll geschrieben. Es
ist eine Mischung aus Teilen ohne Rest und Modulo.

Wenn du es nicht hinbekommst, sag Bescheid...

Ralf

Autor: Ralf Altmann (warpnine)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Thomas,

bist du weitergekommen?
Guck mal unter den Artikeln, da gibts auch was zum 44780, vielleicht
hilft dir das auch schon weiter ?!?

Ralf

Autor: Thomas H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, Ralf!

Habs erst heute mal wieder Zeit, mich damit zu befassen. Die
Cursorsteuerung funktioniert nach wie vor nur für die untere Zeile, in
der oberen kann ich immer nur 1. Zeichen ansprechen. Ich muß da
irgendwo nen ganz ganz dämlichen Denkfehler drin haben...
Werde noch n bisschen dran rumfrickeln.

Th

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Thomas,

wie läufts denn? Bist weitergekommen?

Wegen deinem Cursor-Problem, ich kenn mich mit den HD44780 nicht so
aus, ich benutze Grafikdisplays mit T6963C-Controller, aber ein Freund
hat gemeint, die Adresse 0x40 für die zweite Zeile ist richtig, aber
das Bit 7 spielt da noch ne Rolle. Und wenn du bei 0x40 das Bit 7
setzt, dann kommt ja 0xC0 raus... Gucks dir mal im Datenblatt an, was
das sein könnte...

Ralf

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Ralf.

In der Tat isses so, mit dem C0. Das Bit 7 muss gesetzt sein, damit der
LCD-Controller "weiss", dass das eine Datenposition ist. Du hast das
mit dem 0xC0 richtig erkannt, denn der zu sendende Wert ist immer 80h
(Bit7) + Position. Bei 40h für Zeile 2 Ergibt sich 0xC0. Zeile eins hat
aber "Positionswerte" von 00h..bis..0Fh, also dürfte dann ja Stelle
eins 80h haben, stelle zwei 81h u.s.w. Das klappt aber leider nicht.
Und keiner weiss warum : )

Autor: Ralf Altmann (warpnine)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Thomas,

> also dürfte dann ja Stelle eins 80h haben, stelle zwei 81h u.s.w. Das

> klappt aber leider nicht.

So wie ich es sehe, hast du ja dann eigentlich keinen Fehler mit dem
0xC0, sondern mit dem 0x00, denn ich kann im Datenblatt zum 44780 auf
die schnelle keine Instruktion entdecken, die 0x00 ist...
Erklärs mir bitte nochmal genau, was kommt denn raus, wenn du mit 0x80,
0x81 usw. arbeitest???

Ausserdem ist mir noch was aufgefallen, deine MOVE-Funktion ist so
geschrieben, dass die Zeilenangabe 1 oder 2 sein muss.
Deine Spaltenangabe würde aber 0 als erstes Zeichen der Zeile
akzeptieren. Ist das so beabsichtigt???

Ralf

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ralf!
Danke, dass Du Dich so reinhängst!

Hier erstmal die aktuelle move-funktion:

void move (int cline, int crow)  // Funktion für Cursorbewegung
{             // move (zeile 1...2, Zeichen 1...16)
    char pos;
    if(cline==1) pos=0x80;
    if(cline==2) pos=0xC0;
    pos=pos+crow-1;
    RS=0;RW=0;P2=pos;EN=1;EN=0;
    busychk();            // Fkt. prüft busy-flag
    RS=1;
}

Wir sind uns einig, dass der Wert, der den Cursor positioniert sich
zusammensetzt aus: 0x80 (Bit7 High) PLUS der im Datenblatt angegebenen
Konstante für die Entsprechende Stelle (Also 0x00...0x0F für die obere
und 0x40...0x4F für die untere Zeile). Im klartext bedeutet das, dass
der tatsächlich an das  Display zu übermittelnde Wert 0x80...0x8F für
oben und 0xC0...0xCF für unten ist. Das klappt auch. Allerdings nur für
die Zweite Zeile. Das heisst, 0xC2 schiebt den Cursor an Pos. 3 in der
2ten Zeile. Aber in der ersten funktioniert das prinzip  eben nicht.
Egal, welchen wert von 0x80 bis 0x8F ich sende, der Cursor steht IMMER
an 1er Stelle in der 1ten Zeile. Das ist mein Dilemma.

Zu der Frage mit der Spaltenangabe: Zeichen 1 bis 16 einzugeben geht
schon klar, da in der 3. Zeile von unten ja wieder 1 subtrahiert wird.


Thomas.

Autor: Ralf Altmann (warpnine)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ...da in der 3. Zeile von unten ja wieder 1 subtrahiert wird.
Okay, in deiner LCD2.txt die du gepostet hast, war das noch nicht.

Machen wir das mal Hardcore:
Oben hast du irgendwo erwähnt, dass du Assembler-Code hast, der
funktioniert. Poste bitte mal diesen Assembler-Code, und deine aktuelle
C-Software. Und ich sollte wissen, welchen C-Compiler du verwendest
(Keil?).

Ich wills mir mal auf meinem System angucken.

Ralf

Autor: Thomas (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Ralf.

Nach einer Woche hab ichs endlich mal wieder geschafft, mich mit was
anderem als der Studiererei zu beschäftigen.
Wir machens also mal Hardcore:
Ich hab eben mal lauffähigen assemblercode zusammengekloppt, IDE ist
natöööörlich Keils µV3. Und siehe da: In asm macht der apparat, was er
soll: nämlich den Cursor an die befohlene Adresse setzen. Nur wo ist da
jetzt der unterschied zu meiner C-funktion, die da oben irgendwo
steht???

Grüsse,

Thomas

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> char pos;

Wenn du auf Byteebene arbeitest, dann nimm immer
unsigned char

vor allem wenn du wie hier
pos=pos+crow-1;
Arithmetik machst.

Deine Berechnung könnte man auch kürzer schreiben:

  unsigned char pos;

  pos = 0x80 |                        // Bit 7 für 'Set Cursor'
        ( ( cline - 1 ) << 6 ) |      // Bit 6 fuer Zeile 1 oder 2
        ( crow - 1 );                 // und dann noch die Bits fuer
                                      // die Spalte


Aber das wichtigste: unsigned char, unsigned char, unsigned char!

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank, KH!

Aber leider ist das Resultat das gleiche...
Positionierung Zeile 2 (also move(2,X);) klappt wunderbar, nur Zeile
eins (move(1,X);) will nicht. ganz egal, welchen wert ich für x wähle,
der text beginnt immer in spalte 1. Irgendwie ergibt das keinen
Sinn...

Thomas

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm.
Das ergibt wirklich keinen Sinn.
Eigentlich sollte das so klappen.

Knappes Timing?

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, es geht doch. Das Problem ist jetzt aber: Ich hab das immer
getestet, indem ich die Funktion zwei mal hintereinander aufgerufen
habe und beim ersten mal koordinaten für line1 und in der 2ten funktion
koordination für line2 mitgegeben habe. In etwa so:

....
move(1,3);
printf...;
move(2,4);
printf...;
...

Ich hab das jetzt einfach mal andersrum gemacht, also in etwa so:

...
move(2,3);
printf...;
move(1,3);
printf...;
...

Und es hat sich dabei folgendes herausgestellt: Mit dem der beiden
ersten move-aufruf stimmt was nicht, denn die Daten werden danach immer
an pos 1,1 geschrieben. Muss wohl irgendwie mit ner RS-Vertauschung oder
so zu tun haben. Jedenfalls zweifel ich jetzt nicht mehr an meinem
Verstand sonder nur noch an meiner sorgfalt.

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das fehlende wort lautet *tusch*: ersten!

Mit dem >ERSTEN< der beiden ersten move-aufrufe stimmt was...

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Juhuu! Das Problem mit der Cursoposition ist auf ingenieurs-mässige Art
und Weise gelöst. Nämlich gepfuscht : )
Ich lass halt die move-funktion einmal sinnlos in der
initialisierungssequenz mitlaufen und danach geht das ja dann.
Stellt sich direkt die nächste Frage: Wie ist das mit den Variablen,
die Dezimalwerte enthalten und diese auf dem LCD dargestellt werden
sollen?
Sagen wir mal, eine variable "wert" existiere mit dem dezimalwert
3,14 und ich möchte, daß der dezimale inhalt dieser variable auf dem
lcd ausgegeben wird.
Die Vorgehensweise:

float wert;
void main (void)
{
wert=3,14;
wert=putchar(wert);
printf("%cPi gerundet= ");
printf("%f",wert);
}

bringt's nicht.

Vorschläge werden dankend entgegengenommen   : )

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> printf("%cPi gerundet= ");
Ich denke mal das ist ein Tippfehler beim posten :-)
Muss natürlich
  printf( "Pi gerundet= ");
heissen.


> bringt's nicht.
Was heist das?

Beim gcc, musst du eine andere Library benutzen, wenn du
float Zahlen mit printf ausgeben willst.

Mach ich aber nie, daher weis ich auch nicht auswendig
welche das ist, bzw. wie man die Umschaltung macht.
Stöbere mal im GCC Forum, 'printf' 'Library' 'float'.
Jörg hat das schon öfters erklärt.

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da smit dem wert=3,14; klappt nicht, wenn dann musst du 3.14 schreiben.

Du musst erst in einen Buffer schreiben.

char buffer[17]; // dein display ist ja nur 16 lang, also reichen 17
char *cp;
snprintf(buffer, 17, "PI=rund %f", wert);
cp = &buffer[0];  // oder einfacher cp = buffer;

move(1,1);
while(*cp != '\0') {
  putchar(*cp++);
}

Autor: Thomas H. (bayluga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
snprint???

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
snprintf(): die sichere Alternative zu sprintf.
Man gibt zusätzlich noch die Größe des bereitgestellten
Buffers an. Dadurch ist gewährleistet, dass sprintf
den Buffer nicht überrennt.

Sei C-99 eine Standardfunktion.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank!

sprintf funktionert bestens. Ich durchschau zwar den Mechanismus nicht
wirklich, aber das Resultat zählt.

Cheereo,

Thomas

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.