www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD (HD44780) Amoklauf?


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leute,

so... hier der 1000ste 44780-lcd-Beitrag : )

Ich mach's kurz:
Entwicklungsboard mikroelektronika easyavr5a
uc Atmega8
c mit winavr/gcc
2x16 LCD, Industriestandard
Leine Busy-Abfrage (RW nicht geroutet)
Verdrahtung fix, siehe header.

Hier der Header für die LCD-Funktionen:
/* lcd-routinen hd44780 4-bit */

#include <util/delay.h>
#include <inttypes.h>

#define _lcdport   PORTD
#define _lcddirection  DDRD
#define _rs    PD2
#define _en    PD3
#define _d4    PD4
#define _d5    PD5
#define _d6    PD6
#define _d7    PD7


void initlcd (void);
void lcden (void);
void lcdcom (uint8_t sendbyte);
void lcddata (uint8_t sendbyte);
void lcdstring (char *stringpointer);
char lcdcursor (uint8_t line, uint8_t column);

void initlcd (void) {
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);

  _lcddirection|=(1<<_rs)|(1<<_en)|(1<<_d4)|(1<<_d5)|(1<<_d6)|(1<<_d7);
  _lcdport|=(1<<_d6)|(1<<_d7);  // init command 0x30
  lcden();
  _delay_ms(20);
  lcden();
  _delay_ms(20);
  lcden();
  _delay_ms(20);
  _lcdport=(1<<_d5);    // init command 0x20 4-bit-mode
  _delay_ms(20);
  lcdcom(0b00101000);
  lcdcom(0b00001100);
  lcdcom(0b00010100);
  lcdcom(0b00000110);
  lcdcom(0b00000001);
  lcdcom(2);
  _delay_ms(20);

  }
  
void lcden (void) {      // enable-pulse 
  _lcdport|=(1<<_en);
  _delay_ms(1);
  _lcdport&=~(1<<_en);
  _delay_ms(1);
  }
  
void lcdcom (uint8_t sendbyte) {
_lcdport=sendbyte;      // erst upper nibble
_lcdport=_lcdport&0xF0;      // mask lower nibble
lcden();        
sendbyte=sendbyte<<4;      // lower nibble hochschieben
_lcdport=sendbyte;          
_lcdport=_lcdport&0xF0;      // mask lower nibble    
lcden();
}

void lcddata (uint8_t sendbyte) {
_lcdport=sendbyte;      // erst upper nibble
_lcdport=_lcdport&0xF0;      // mask lower nibble
_lcdport|=(1<<_rs);      // rs setzen, daten
lcden();              
sendbyte=sendbyte<<4;      // lower nibble hochschieben
_lcdport=sendbyte;          
_lcdport=_lcdport&0xF0;      // mask lower nibble
_lcdport|=(1<<_rs);      // rs setzen, daten        
lcden();              
_lcdport&=~(1<<_rs);      // rs zurücksetzen


void lcdstring (char *stringpointer){
  while(*stringpointer)
    lcddata(*stringpointer++);
  }


Jetzt die Preisfrage:
Wenn ich den header includiere, die init gefolgt von einer Textausgabe 
aufrufe, passiert folgendes:
- Es werden je nach Text tlw. völlig sinnlose Zeichen ausgegeben. So 
führt zum Beispiel der String "Test" zur Ausgabe von "Test". Der String 
"KURTKROEMER" bringt aber "D_einhalb_U%". Mehr als vier Zeichen werde 
nie angezeigt. Selstamerweise verhält es sich bei einem Einzelnen 
Zeichen (gehen auch nich alle. "Q" z.B. geht) so, dass exakt jeder 
zweite Reset eine Ausgabe bringt. In den Resets dazwischen wird nichts 
angezeigt.
Hat jemand die Glaskugel gerade NICHT in reparatur und eine Idee?
Oder vielleicht zufällig gerade was in der Richtung aufgebaut, um den 
Code an einem Anderen Display zu testen?

Tausen Dank im Voraus,

Thomas

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Leine Busy-Abfrage (RW nicht geroutet)

Was heißt nicht gerouted? Der Pin gehört auf Masse.

  _lcdport|=(1<<_d6)|(1<<_d7);  // init command 0x30

Das ergibt für mich 0xC0, aber nicht 0x30.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


void lcdcom (uint8_t sendbyte) {
_lcdport=sendbyte;      // erst upper nibble
_lcdport=_lcdport&0xF0;      // mask lower nibble
lcden();

Du schreibst hier sendbyte auf _lcdport.
Damit setzt Du aber je nach Inhalt der unteren 4 Bit sowohl RS als auch 
E auf irgendeinen Pegel...

Gruß aus Berlin
Michael

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, Holger.

Korrekt wäre gewesen: "Nicht zum Controller geroutet". Der Pin liegt auf 
Masse.

Und mit der 0xC0 hast Du durchaus recht.
Aber es ändert leider auch nichts... : (

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Micha,

jau das ist klar, aber mach ja nix. Auf den unteren 4 Bit befinden sich 
ja nur noch RS (wird nach der Maskierung einzeln gesetzt) und EN.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Thomas schrieb:

> Hallo Micha,
>
> jau das ist klar, aber mach ja nix. Auf den unteren 4 Bit befinden sich
> ja nur noch RS (wird nach der Maskierung einzeln gesetzt) und EN.

wie verhält sich das Display, wenn unten bei
_lcdport=sendbyte;      // erst upper nibble

RS und E oder nur E zufällig auf H gesetzt werden und mit

_lcdport=_lcdport&0xF0;      // mask lower nibble

anschließend auf L?

Dann hast Du einen E-Impuls im falschen Mode erzeugt oder mit falschen 
Daten.
Anschließend machst Du den regulären E-Impuls und das Display liest die 
Datenbits nochmal als Data ein usw.

Gruß aus Berlin
Michael

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So... nochmal drüber nachgedacht und zum Schluss gekommen, dass es wohl 
doch nicht ganz so egal ist.
Hier die bis hierhin korrigierte Version.
Init klappt jetzt immer (nicht nur bei jedem 2. Reset o.ä.), Ausgabe ist 
aber noch nicht Korrekt... Es wird immer das gleiche Zeichen bei einem 
String ausgegeben.

/* lcd-routinen hd44780 4-bit */

#include <util/delay.h>
#include <inttypes.h>

#define _lcdport     PORTD
#define _lcddirection  DDRD
#define _rs        PD2
#define _en        PD3
#define _d4        PD4
#define _d5        PD5
#define _d6        PD6
#define _d7        PD7


void initlcd (void);
void lcden (void);
void lcdcom (uint8_t sendbyte);
void lcddata (uint8_t sendbyte);
void lcdstring (char *stringpointer);
char lcdcursor (uint8_t line, uint8_t column);

void initlcd (void) {
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);
_delay_ms(20);

  _lcddirection|=(1<<_rs)|(1<<_en)|(1<<_d4)|(1<<_d5)|(1<<_d6)|(1<<_d7);
  _lcdport=(0x30);  // init command 0x30
  lcden();
  _delay_ms(20);
  lcden();
  _delay_ms(20);
  lcden();
  _delay_ms(20);
  _lcdport=(0x20);  // init command 0x20 4-bit-mode
  _delay_ms(20);
  lcdcom(0b00101000);
  lcdcom(0b00001100);
  lcdcom(0b00010100);
  lcdcom(0b00000110);
  lcdcom(0b00000001);
  lcdcom(2);
  _delay_ms(20);

  }
  
void lcden (void) {    // enable-pulse 
  _lcdport|=(1<<_en);
  _delay_ms(1);
  _lcdport&=~(1<<_en);
  _delay_ms(1);
  }
  
void lcdcom (uint8_t sendbyte) {
sendbyte=sendbyte&0xF0;
_lcdport|=sendbyte;    // erst upper nibble
lcden();        
sendbyte=sendbyte<<4;
sendbyte=sendbyte&0xF0;    // lower nibble hochschieben
_lcdport|=sendbyte;    // mask lower nibble    
lcden();
}

void lcddata (uint8_t sendbyte) {
sendbyte=sendbyte&0xF0;
_lcdport|=sendbyte;    // erst upper nibble      
_lcdport|=(1<<_rs);    // rs setzen, daten
lcden();              
sendbyte=sendbyte<<4;
sendbyte=sendbyte&0xF0;    // lower nibble hochschieben
_lcdport|=sendbyte;              // mask lower nibble
_lcdport|=(1<<_rs);    // rs setzen, daten        
lcden();              
_lcdport&=~(1<<_rs);    // rs zurücksetzen
}

void lcdstring (char *stringpointer){
while(*stringpointer)
lcddata(*stringpointer++);
  }


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@micha.
Da hab ich nochmal nachsinniert und ERST die Maskierung gemacht (s.o.)
Danke für den Hinweis!

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

gerade Deine neue Version gesehen:

sendbyte=sendbyte&0xF0;
_lcdport|=sendbyte;    // erst upper nibble

Auch hier wieder: was ist, wenn das RS-Bit H ist bei Daten?

Nur Datenbits des Ports auf L setzen.
Daten in Hilfvariable an die passende Stelle legen, Steuerbits auf L 
setzen und mit dem Portinhalt vor-odern als Möglichkeit.

_lcdport &= 0x0F;
temp = sendbyte & 0xF0;
_lcdport |= temp;
lcden();
_lcdport &= 0x0F;
temp = (sendbyte<<4) & 0xF0;
_lcdport |= temp;
lcden();

sollte passen.

Gruß aus Berlin
Michael

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm...
RS kann doch nach der verUNDung "&0xF02" gar nicht mehr H sein. Und wenn 
ich es für Daten brauche, setz ich es ja "manuell" in der nächsten Zeile 
mit |(1<<_RS).
Oder ich steh komplett auf dem Schlauch?

Ahoi,

Thomas

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich kann nicht verstehen, warum jemand Probleme mit LCDs hat.
Bei mir laufen sie alle "like a charm" an jedem beliebigen Pin:

http://www.mikrocontroller.net/attachment/30300/lcd_drv.zip


Ich kann die Bitmacros nur jedem empfehlen. Es wird vieles einfacher und 
erheblich besser lesbar.


Peter

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo peda.

Ich weiss auch nicht, warum ich da immer wieder mit kämpfen muss.
Werde in kürze mal Deinen TIp ausprobieren.

Melde mich dann bestimmt, wenn ich nicht kaper wie's läuft : )

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie erwartet : )

Ich bekomm beim compilieren von main.c (und natprlich lcd_drv.c) ne 
Fehlermeldung, mit der ich mal gar nichts anfangen kann.. voltile struct 
bits...

>Compiling C: lcd_drv.c
>avr-gcc -c -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes 
-Wa,-adhlns=./lcd_drv.lst  -std=gnu99 -Wundef -MMD -MP -MF .dep/lcd_drv.o.d 
lcd_drv.c -o lcd_drv.o
>lcd_drv.c:4:1: warning: "F_CPU" redefined
><command-line>: warning: this is the location of the previous definition
>lcd_drv.c: In function 'lcd_init':
>lcd_drv.c:60: error: 'volatile struct bits' has no member named 'b'
>make.exe: *** [lcd_drv.o] Error 1

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas schrieb:
>>lcd_drv.c:4:1: warning: "F_CPU" redefined

Dann nimm eben eine Definition raus.

>>lcd_drv.c:60: error: 'volatile struct bits' has no member named 'b'
>>make.exe: *** [lcd_drv.o] Error 1

Dazu müßte man die Zeile 60 wissen.
Sende einfach mal den kompletten Code als Anhang.


Peter

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peda,

die redefinition ist ja nicht so wild...
Anbei ein zip.

Danke mal wieder,

Thomas

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommando zurück, alles Wolke!

PeDas code läuft. Will jetzt mal sehen, worans bei mir lag.
Danke!

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.