Forum: Mikrocontroller und Digitale Elektronik LCD Routine klappt nicht


von Jürgen (Gast)


Lesenswert?

Ich nutze immer wieder gerne mal die LCD Routine von MyAVR.
Normalerweise ist das Display in dieser Routine folgendermaßen 
angeschlossen:

Bit 4-7 - PortD Bit 4-7 ----> Neu PortD Bit 0-3
RS      - PortD Bit 2   ----> Neu PortD Bit 5
E       - PortD Bit 3   ----> Neu PortD Bit 4

Ich war eigentlich der Meinung ich hätte alles soweit angepasst aber bis 
auf jeweils einen schwarzen Balken in Zeile 1 und 2 kommt leider nichts.

Ich gehe davon aus das ich in der lcd_send Routine etwas falsch habe.
Ich habe im übrigen ein 4x20 Zeilen Display und betreibe es im 4 Bit 
Modus.

Hier mal die gesamten Funktionen.
Bedanke mich jetzt schonmal für jegliche Hilfe.

1
//========================================================
2
void lcd_send(char data)
3
{
4
  char rs=PORTD;
5
  rs&=20;        // aktuelles RS ermitteln
6
  
7
  char tmp=data;   // high teil
8
  tmp&=0xf0;
9
  tmp = tmp >> 4;
10
  tmp|=rs;
11
  
12
  PORTD=tmp;
13
  
14
  sbi(PORTD,4);  // schreiben
15
  cbi(PORTD,4);
16
  
17
  tmp=data;      // low teil
18
  tmp&=0x0f;
19
         tmp*=16;
20
  tmp|=rs;
21
  
22
  PORTD=tmp;
23
  
24
  sbi(PORTD,4);  // schreiben
25
  cbi(PORTD,4);
26
  waitMs(1);
27
}
28
//========================================================
29
void lcd_cmd(char cmd)
30
{
31
  cbi(PORTD,5);    
32
  lcd_send(cmd);  
33
}
34
//========================================================
35
void lcd_write(char text)
36
{
37
  sbi(PORTD,5);    
38
  lcd_send(text);
39
}
40
//========================================================
41
void lcd_write(const char* pText)
42
{
43
  while(pText[0]!=0)
44
  {
45
    lcd_write(pText[0]);
46
    pText++;
47
  }
48
}
49
//========================================================
50
void lcd_write(char* pText, int count)
51
{
52
  while(count!=0)
53
  {
54
    lcd_write(pText[0]);
55
    pText++;
56
    count--;
57
  }
58
}
59
//========================================================
60
void lcd_home()
61
{
62
  lcd_cmd(0x02);
63
  waitMs(2);      
64
}
65
//========================================================
66
void lcd_clear()
67
{
68
  lcd_cmd(0x01);
69
  waitMs(2);      
70
}
71
//========================================================
72
void lcd_on()
73
{
74
  lcd_cmd(0x0E);
75
}
76
//========================================================
77
void lcd_off()
78
{
79
  lcd_cmd(0x08);
80
}
81
//========================================================
82
void lcd_goto(int row, int col)
83
{
84
  row--;        
85
  row&=0x01;      
86
  row*=0x40;      
87
  col--;        
88
  col&=0x0f;      
89
  char tmp=row|col;
90
  tmp|=0x80;      
91
  lcd_cmd(tmp);    
92
}
93
//========================================================
94
void lcd_init()
95
{
96
  PORTD = 0b00000011;  // soft reset
97
  sbi(PORTD,4);
98
  cbi(PORTD,4);
99
  waitMs(5);
100
  PORTD = 0b00000011;  
101
  sbi(PORTD,4);
102
  cbi(PORTD,4);
103
  waitMs(1);
104
  PORTD = 0b00000011;  
105
  sbi(PORTD,4);
106
  cbi(PORTD,4);
107
  waitMs(5);
108
  
109
  PORTD=0b00000010; // 4 Bit aktivieren
110
  sbi(PORTD,4);
111
  cbi(PORTD,4);
112
  waitMs(5);
113
114
  lcd_cmd (0b00101000); // function set  
115
  lcd_cmd (0b00000110); // entry mode
116
  lcd_on();
117
  lcd_clear(); 
118
  
119
}
120
//========================================================

von Karl H. (kbuchegg)


Lesenswert?

1
  sbi(PORTD,4);  // schreiben
2
  cbi(PORTD,4);
3
  
4
  tmp=data;      // low teil
5
  tmp&=0x0f;
6
         tmp*=16;
7
  tmp|=rs;

Wieso *16?
Dadurch verschiebst du ja die unteren 4 Bits in die höheren 4 Bits.

> ch war eigentlich der Meinung ich hätte alles soweit angepasst
> aber bis auf jeweils einen schwarzen Balken in Zeile 1 und 2 kommt
> leider nichts.

Normalerweise ein Indiz, dass die Intialisierung nicht klappt.

von mschoeldgen (Gast)


Lesenswert?

Jürgen schrieb:
> PORTD=tmp;

Mit dem Befehl überschreibst du auch die Kontrollsignale, die müssen 
vorher ausmaskiert bzw. reinverODERert werden z.B.
rs = PIND & 0xf0;
PORTD = rs | tmp;

von Klaus (Gast)


Lesenswert?

Tschuldigung!

mir schmerzen irgendwie die Augen!

Bekommst du keine Fehlermeldungen 3 mal lcd_write??


void lcd_write(char text)
void lcd_write(const char* pText)

void lcd_write(char* pText, int count)
{
  while(count!=0)
  {
    lcd_write(pText[0]);    Irgendwie sieht das nach Rekursiven aufruf 
aus.
    pText++;
    count--;
  }
}

In der Init_routine vermisse ich den Löschbefehl.
Auserdem werden die Comandos nicht im 4-Bit Modus gesendet.

Also ab hier:
  lcd_cmd (0b00101000); // function set
  lcd_cmd (0b00000110); // entry mode
  lcd_on();
  lcd_clear();

von Jürgen (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wieso *16?
>
> Dadurch verschiebst du ja die unteren 4 Bits in die höheren 4 Bits.

Sorry stimmt das kam noch aus der originalen Routine.

Aber selbst ohne funktioniert es leider nicht.

Ich habe ehrlich gesagt auch das Gefühl, das das Display gar nicht 
wirklich bootet.

Vielleicht ist irgendetwas am Function set krumm.

von Klaus (Gast)


Lesenswert?

Sorry!

void lcd_cmd(char cmd)
{
  cbi(PORTD,5);
  lcd_send(cmd);
}


übersehen!

von Karl H. (kbuchegg)


Lesenswert?

Kannst du nicht das LCD erst mal temporär so verkabeln, dass du die 
Originalroutine benutzen kannst?

Dann weißt du wenigstens, ob es Timingprobleme gibt.

schwarze Balken deuten darauf hin, dass die Initialisierung schon nicht 
klappt. Und das ist meistens ein Timimgproblem.

von Jürgen (Gast)


Lesenswert?

Also es war der Watchdog Timer an sodass gar nichts passierte.

Hab den jetzt soweit rausgenommen und das Display bootet zumindest 
schonmal. Die schwarzen Balken sind also weg.

Eine Ausgabe bekomme ich dennoch nicht hin ?!

von Jürgen (Gast)


Lesenswert?

Ok zur allgemeinen Info.
Jetzt klappt alles. Ich musste nur noch rs&=20 gegen rs&=0b00100000 
tauschen

von Düsendieb (Gast)


Lesenswert?

Jürgen schrieb:
> Ok zur allgemeinen Info.
> Jetzt klappt alles. Ich musste nur noch rs&=20 gegen rs&=0b00100000
> tauschen

Tja, 20 ist ungleich 0x20

von Karl H. (kbuchegg)


Lesenswert?

Jürgen schrieb:
> Ok zur allgemeinen Info.
> Jetzt klappt alles. Ich musste nur noch rs&=20 gegen rs&=0b00100000
> tauschen

Argh. Und ich bin das ganze ein paar mal im Kopf duchgegangen und hab 
intuitiv 0x20 gelesen.

Ein Tipp.
Spar dir diese Zahlen! Schreib das ganze so:
1
#define RS_PIN     5
2
#define E_PIN      4
3
4
5
void lcd_send(char data)
6
{
7
  char rs=PORTD;
8
  rs &= (1<<RS_PIN);
9
  
10
  char tmp=data;   // high teil
11
  tmp&=0xf0;
12
  tmp = tmp >> 4;
13
  tmp|=rs;
14
  
15
  PORTD=tmp;
16
  
17
  sbi(PORTD,E_PIN);  // schreiben
18
  cbi(PORTD,E_PIN);
19
...
20
21
void lcd_cmd(char cmd)
22
{
23
  cbi(PORTD,RS_PIN);    
24
  lcd_send(cmd);  
25
}
26
....

und natürlich überall anders auch die konstanten Zahlen gegen Makros 
austauschen. Dann passieren dir nicht solche Flüchtigkeitsfehler und 
eine Anpassung an andere Pin-Nummern ist auch einfacher: einfach nur im 
#define die andere Zahl eintragen und den Rest macht der Compiler.
(Man kann das auch mit den Datenleitungen so hinkriegen, allerdings wird 
der Code dann ein wenig komplizierter)

Es liegt in deiner Hand, dir den Code so zu gestalten, dass du wenige 
bis keine Portierungsfehler machen kannst. Du musst es nur tun! Die 
Zeit, die du jetzt für Fehlersuche verbraten hast, ist ein Vielfaches 
dessen, was dir eine derartige Codeänderung zeitmässig gekostet hätte.

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.