mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD halb defekt?


Autor: Der Lars (vhdl-neuling)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich lerne aus meinen Fehlern am Wochenende und poste mal einen neuen 
Thread :)

Alsooo: habe das 16x1 LCD-Display von Reichelt (161A) und habe folgendes 
Problem.
Ich habs initialisiert (8-bit-Modus, 1-zeilig) und ich kann auch schön 
was in die ersten 8 Stellen schreiben. ABER die 2. acht Stellen kann ich 
nicht ansprechen. Wenn ich das Display 2-zeilig initialisiere, kommt gar 
nichts. Wenn ich einen elend langen String aufs Display schicke 
(1-zeilig), kommt nach exakt 80 Zeichen erneut etwas auf den ersten 8 
Stellen des Displays.

Das habe ich mir so erklärt: Das Data-Display-RAM ist 0x4F bits breit 
und wenn der Cursor da einmal durchgelaufen ist, gehts von vorne wieder 
los.

Im Datenblatt steht, dass 0x40 bis 0x47 im RAM die Stellen 9-16 
repräsentieren, aber das kann ja irgendwie nicht sein. Kann es sein, 
dass die Stellen 9-16 einfach falsch oder gar nicht gemappt sind?

Anders kann ich es mir nicht erklären.

Danke schonmal,
derLars

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Lars wrote:
> Ich habs initialisiert (8-bit-Modus, 1-zeilig) und ich kann auch schön
> was in die ersten 8 Stellen schreiben. ABER die 2. acht Stellen kann ich
> nicht ansprechen.

Das ist normal, denn das Display ist 2 Zeilig, die zweite Hälfte ist 
elektrisch gesehen die zweite Zeile.

> Wenn ich das Display 2-zeilig initialisiere, kommt gar nichts.

Dann dreh mal den Kontrast höher.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Hälfte Adr. 0x00
2. Hälfte Adr. 0x50

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus wrote:

> 2. Hälfte Adr. 0x50

Nein, 0x40 ist schon richtig.

Autor: Lupin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die zweite Hälfte beginnt ab 0x40 (nicht 0x50).

Ist irgendwie doof gemacht, ich hab mir eine Funktion geschrieben welche 
schaut wo das Zeichen hin soll und danach dann die entsprechende "Zeile" 
auswählt (also vor jedem Schreiben den Cursor manuell setzen).

Den PIC Code hatte ich hier mal hoch geladen:
Beitrag "LM75 Thermometer"

Interessant für dich sind wohl die Funktionen InitLcd und PrintLCD_Char.

Autor: Der Lars (vhdl-neuling)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unfassbar es klappt! :D

Der Tipp mit dem Kontrast hats gebracht. Muss man auch erstmal drauf 
kommen, dass der Kontrast sich bei den Modi ändert!

Danke Lupin für den Link, aber ich bleibe doch lieber bei C ;)

Die Initialisierung hatte ja auch so schon geklappt und die Funktion 
set_cursor für mehrere Zeilen hab ich mir zurechtgestrickt.

Danke an alle :)

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Lars wrote:
> Der Tipp mit dem Kontrast hats gebracht. Muss man auch erstmal drauf
> kommen, dass der Kontrast sich bei den Modi ändert!

Wenn das Display mit einer Zeile läuft, dann werden 8 Pixelzeilen 
nacheinander angesteuert, jede Pixelzeile ist 1/8 der Zeit an.
Bei 2 Zeilen werden 16 Pixelzeilen angesteuert, jede Pixelzeile ist 
daher nur 1/16 an. Um dennoch die gleiche Spannung an jeden Pixel 
anzulegen, muss die Spannung daher höher sein (etwa um Wurzel 2 wegen 
dem Effektivwert).

Autor: Der Lars (vhdl-neuling)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Benedikt

Danke für die Erklärung, das leuchtet ein! :)

Hätte noch eine weite LCD-Frage und weiß nicht ob ich extra nen neuen 
Thread öffnen soll.

Wenn ich eine Variable ausgeben möchte, gibt er mir ja mit LCD_data(var) 
den ASCI-Code des Wertes der Variablen aus. Aber was muss ich tun, damit 
das Display mir den wirklichen Wert ausgibt?

Danke,
derLars

Autor: Dieter Engelhardt (netdieter) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Such mal nach sprintf()
Das tut den Trick ;-)

Autor: Der Lars (vhdl-neuling)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis!

Hab mir jetzt etwas zusammen geschustert, aber so ganz funktioniert das 
nicht, wenn das Ergebnis auch hübsche Zeichen zutage bringt.
  int test=23;
  lcd_var(test);

void lcd_var(unsigned int temp1)
{
   int lf;
   char eingabe[2];
   
   LCD_COMMAND_PORT |= 0x01;         // RS auf 1 setzen
 
   sprintf(eingabe,"%d",temp1);
 
   for (lf=2;lf>0;lf--){
     LCD_PORT = eingabe[lf];               // setzen
     lcd_enable();         // übergeben
     waitms(10);
   }
}

Habs wohl doch noch nicht so recht verstanden. :-/

Autor: Dieter Engelhardt (netdieter) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn LCD_data(var) bereits den ASCII-Code ausgibt, dann must Du den 
Inhalt der Variable nur noch nach ASCII transformieren.

Also in Etwas so:
 int test=23;
 char Buffer[128];

 sprintf( Buffer, "%d", test );
 LCD_Data(Buffer);




Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal so,

sprintf(&eingabe[0],"%d",temp1);

So wie ich das gelernt hab ist eingabe[2] ein Array.Wenn du was rein 
schreiben möchtest, musst du mit einem Zeiger auf die Stelle verweisen 
an der du mit dem schreiben beginnen möchtest.

&eingabe[0] = ein Zeiger auf die stelle 0 des Arrays eingabe[2]

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael wrote:

> &eingabe[0] = ein Zeiger auf die stelle 0 des Arrays eingabe[2]

Ob eingabe oder &eingabe[0] ist egal, denn beides ist ein Zeiger auf den 
Anfang des Arrays.

Autor: Der Lars (vhdl-neuling)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Dieter :)

lcd_data macht es nicht, aber wie im Tutorial funktioniert lcd_string 
damit.

Gruß vom Lars

Nachtrag: Und danke dem Rest :o)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Fehler dürfte gewesen sein, dass du hier
void lcd_var(unsigned int temp1)
{
   int lf;
   char eingabe[2];

Das Array eingabe viel zu klein dimensioniert hast.
Das String Array hat eine Länge von 2 Elementen. Jeder C-String wird mit 
einem 0-Byte abgeschlossen. Das wiederrum bedeutet, dass deine Zahl in 
temp1 nur 1-stellig sein darf, weil du ja im Array nur Platz für 1 
Zeichen hast.

An solchen Stellen ist falscher Geiz absolut kontraproduktiv.
Ein unsigned int kann Werte bis 65536 annehmen. Das sind 5 Stellen. Du 
brauchst also als minimale Arraygröße 6 (wegen dem abschliessenden 
0-Byte).
Aber nicht kleckern, klotzen. Gib dir noch ein paar Bytes Reserve dazu 
...
void lcd_var(unsigned int temp1)
{
   int lf;
   char eingabe[64];

... denn irgendwann machst du folgendes:
     sprintf( eingabe, "Ausgabewert: %d V", temp1 );

und dann sind deine maximal 5 möglichen Zeichen in Eingabe schon wieder 
zuwenig und du suchst dir einen Wolf, wo der Fehler liegt.

Auch mal einen Blick auf snprintf werfen.

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.