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


von Thomas (Gast)


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:
1
/* lcd-routinen hd44780 4-bit */
2
3
#include <util/delay.h>
4
#include <inttypes.h>
5
6
#define _lcdport   PORTD
7
#define _lcddirection  DDRD
8
#define _rs    PD2
9
#define _en    PD3
10
#define _d4    PD4
11
#define _d5    PD5
12
#define _d6    PD6
13
#define _d7    PD7
14
15
16
void initlcd (void);
17
void lcden (void);
18
void lcdcom (uint8_t sendbyte);
19
void lcddata (uint8_t sendbyte);
20
void lcdstring (char *stringpointer);
21
char lcdcursor (uint8_t line, uint8_t column);
22
23
void initlcd (void) {
24
_delay_ms(20);
25
_delay_ms(20);
26
_delay_ms(20);
27
_delay_ms(20);
28
_delay_ms(20);
29
30
  _lcddirection|=(1<<_rs)|(1<<_en)|(1<<_d4)|(1<<_d5)|(1<<_d6)|(1<<_d7);
31
  _lcdport|=(1<<_d6)|(1<<_d7);  // init command 0x30
32
  lcden();
33
  _delay_ms(20);
34
  lcden();
35
  _delay_ms(20);
36
  lcden();
37
  _delay_ms(20);
38
  _lcdport=(1<<_d5);    // init command 0x20 4-bit-mode
39
  _delay_ms(20);
40
  lcdcom(0b00101000);
41
  lcdcom(0b00001100);
42
  lcdcom(0b00010100);
43
  lcdcom(0b00000110);
44
  lcdcom(0b00000001);
45
  lcdcom(2);
46
  _delay_ms(20);
47
48
  }
49
  
50
void lcden (void) {      // enable-pulse 
51
  _lcdport|=(1<<_en);
52
  _delay_ms(1);
53
  _lcdport&=~(1<<_en);
54
  _delay_ms(1);
55
  }
56
  
57
void lcdcom (uint8_t sendbyte) {
58
_lcdport=sendbyte;      // erst upper nibble
59
_lcdport=_lcdport&0xF0;      // mask lower nibble
60
lcden();        
61
sendbyte=sendbyte<<4;      // lower nibble hochschieben
62
_lcdport=sendbyte;          
63
_lcdport=_lcdport&0xF0;      // mask lower nibble    
64
lcden();
65
}
66
67
void lcddata (uint8_t sendbyte) {
68
_lcdport=sendbyte;      // erst upper nibble
69
_lcdport=_lcdport&0xF0;      // mask lower nibble
70
_lcdport|=(1<<_rs);      // rs setzen, daten
71
lcden();              
72
sendbyte=sendbyte<<4;      // lower nibble hochschieben
73
_lcdport=sendbyte;          
74
_lcdport=_lcdport&0xF0;      // mask lower nibble
75
_lcdport|=(1<<_rs);      // rs setzen, daten        
76
lcden();              
77
_lcdport&=~(1<<_rs);      // rs zurücksetzen
78
79
80
void lcdstring (char *stringpointer){
81
  while(*stringpointer)
82
    lcddata(*stringpointer++);
83
  }

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

von holger (Gast)


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.

von Michael U. (amiga)


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

von Thomas (Gast)


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... : (

von Thomas (Gast)


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.

von Michael U. (amiga)


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

von Thomas (Gast)


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.
1
/* lcd-routinen hd44780 4-bit */
2
3
#include <util/delay.h>
4
#include <inttypes.h>
5
6
#define _lcdport     PORTD
7
#define _lcddirection  DDRD
8
#define _rs        PD2
9
#define _en        PD3
10
#define _d4        PD4
11
#define _d5        PD5
12
#define _d6        PD6
13
#define _d7        PD7
14
15
16
void initlcd (void);
17
void lcden (void);
18
void lcdcom (uint8_t sendbyte);
19
void lcddata (uint8_t sendbyte);
20
void lcdstring (char *stringpointer);
21
char lcdcursor (uint8_t line, uint8_t column);
22
23
void initlcd (void) {
24
_delay_ms(20);
25
_delay_ms(20);
26
_delay_ms(20);
27
_delay_ms(20);
28
_delay_ms(20);
29
30
  _lcddirection|=(1<<_rs)|(1<<_en)|(1<<_d4)|(1<<_d5)|(1<<_d6)|(1<<_d7);
31
  _lcdport=(0x30);  // init command 0x30
32
  lcden();
33
  _delay_ms(20);
34
  lcden();
35
  _delay_ms(20);
36
  lcden();
37
  _delay_ms(20);
38
  _lcdport=(0x20);  // init command 0x20 4-bit-mode
39
  _delay_ms(20);
40
  lcdcom(0b00101000);
41
  lcdcom(0b00001100);
42
  lcdcom(0b00010100);
43
  lcdcom(0b00000110);
44
  lcdcom(0b00000001);
45
  lcdcom(2);
46
  _delay_ms(20);
47
48
  }
49
  
50
void lcden (void) {    // enable-pulse 
51
  _lcdport|=(1<<_en);
52
  _delay_ms(1);
53
  _lcdport&=~(1<<_en);
54
  _delay_ms(1);
55
  }
56
  
57
void lcdcom (uint8_t sendbyte) {
58
sendbyte=sendbyte&0xF0;
59
_lcdport|=sendbyte;    // erst upper nibble
60
lcden();        
61
sendbyte=sendbyte<<4;
62
sendbyte=sendbyte&0xF0;    // lower nibble hochschieben
63
_lcdport|=sendbyte;    // mask lower nibble    
64
lcden();
65
}
66
67
void lcddata (uint8_t sendbyte) {
68
sendbyte=sendbyte&0xF0;
69
_lcdport|=sendbyte;    // erst upper nibble      
70
_lcdport|=(1<<_rs);    // rs setzen, daten
71
lcden();              
72
sendbyte=sendbyte<<4;
73
sendbyte=sendbyte&0xF0;    // lower nibble hochschieben
74
_lcdport|=sendbyte;              // mask lower nibble
75
_lcdport|=(1<<_rs);    // rs setzen, daten        
76
lcden();              
77
_lcdport&=~(1<<_rs);    // rs zurücksetzen
78
}
79
80
void lcdstring (char *stringpointer){
81
while(*stringpointer)
82
lcddata(*stringpointer++);
83
  }

von Thomas (Gast)


Lesenswert?

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

von Michael U. (amiga)


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

von Thomas (Gast)


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

von Peter D. (peda)


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

von Thomas (Gast)


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 : )

von Thomas (Gast)


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

von Peter D. (peda)


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

von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Peda,

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

Danke mal wieder,

Thomas

von Thomas (Gast)


Lesenswert?

Kommando zurück, alles Wolke!

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

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.