Forum: Mikrocontroller und Digitale Elektronik HD44780 Custom Characters Problem


von Nino K. (lnino)


Angehängte Dateien:

Lesenswert?

Hallo an alle,

bin gerade dabei an mein HD44780 Display Custom Characters zu senden.
Nach dem Lesen des Datenblattes denke ich, dass ich das System 
verstanden habe, aber leider zeigt das Display nichts an.

Es können maximal 8 Custom Characters gespeichert werden.
Zum CGRAM wechselt man mit 0x40.
Zum DDRAM wechselt man mit 0x80.

Anschließend kann man mit 0x00 den ersten Custom Character aufrufen, 
sofern man mit 0x40 begonnen hat.

Auf dieser Website war das auch super erklärt: 
http://www.8051projects.net/lcd-interfacing/lcd-custom-character.php

Das Display selber funktioniert, ich kann auch normalen Text darauf 
ausgeben. Verkabelung passt auch. RS ist mit PD7 verkabelt.

Ich finde den Fehler einfach nicht, hat jemand einen Lösungsansatz für 
mich? Irgendetwas muss ich übersehen.

An den Thread habe ich meinen vollständigen Quellcode und einen Teil der 
LCD Lib angehängt. Das ganze stammt von einem Nerdkit. Dies bedeutet ich 
verwende einen ATMega168 als MCU.

Danke schon mal für die Unterstützung.

von John (Gast)


Lesenswert?

Nino K. schrieb:
> Irgendetwas muss ich übersehen.
1
lcd_set_type_command();     // Change into command mode
2
lcd_write_byte(0x80);       // Change to DDRAM
3
4
lcd_home();
5
lcd_write_byte(0x00);       // Show stored custom character on lcd screen

Hallo Nino,
macht
1
lcd_home();
automatisch auch
1
lcd_set_type_data();

Wenn nicht, dann musst Du das selber umstellen.
Die home-Funktion befindet sich leider nicht im angehängten Teil deiner 
LCD Lib.

Und
1
lcd_home();
setzt den Cursor schon auf die erste Stelle im Display. Davor die 
DDRAM-Adresse zu setzen ist überflüssig.

Gruß
John

von Nino K. (lnino)


Lesenswert?

Hi John,

danke für die Rückmeldung.

lcd_home() macht folgendes:
1
void lcd_home() {
2
  lcd_set_type_command();
3
  lcd_write_byte(0x02);
4
  delay_ms(50);
5
}

Dann sollte es mit dem folgenden Code funktionieren? Sofern ich dich 
richtig verstanden habe. Ich habe das "lcd_home()" durch 
"lcd_set_type_data()" ersetzt. Oder muss ich noch etwas dabei beachten?
1
#define F_CPU 14745600
2
 
3
#include <stdio.h>
4
 
5
#include <avr/io.h>
6
#include <avr/pgmspace.h>
7
#include <inttypes.h>
8
 
9
#include <inttypes.h>
10
#include <string.h>
11
 
12
#include <util/delay.h>
13
#include "../libnerdkits/delay.h"
14
#include "../libnerdkits/lcd.h"
15
16
int main(void) {
17
18
  // fire up the LCD
19
  lcd_init();
20
  lcd_home();
21
22
lcd_set_type_command();     // Change into command mode
23
lcd_write_byte(0x40);       // Change to CGRAM to store custom character - at 0x00
24
lcd_set_type_data();        // Change into data mode
25
26
lcd_write_byte(0x00);       // Send Hexa Bytes of Custom Character Begin
27
lcd_write_byte(0x0E);
28
lcd_write_byte(0x1F);
29
lcd_write_byte(0x1F);
30
lcd_write_byte(0x1F);
31
lcd_write_byte(0x0E);
32
lcd_write_byte(0x00);
33
lcd_write_byte(0x00);       // Send Hexa Bytes of Custom Character End
34
35
lcd_set_type_command();     // Change into command mode
36
lcd_write_byte(0x80);       // Change to DDRAM
37
38
lcd_set_type_data();
39
lcd_write_byte(0x00);       // Show stored custom character on lcd screen
40
41
  // busy loop
42
  while(1) {
43
44
  // do nothing
45
  }
46
47
  return 0;
48
}

von John (Gast)


Lesenswert?

Ja, sollte so funktionieren.

von Nino K. (lnino)


Lesenswert?

John schrieb:
> Ja, sollte so funktionieren.

Und das tut es auch. Vielen vielen Dank für deine Hilfe.
Habe es gerade getestet. Bin echt nicht darauf gekommen, dass ich das 
Laden des Custom Characters im Data Modus machen muss. Juhu.

von Karl H. (kbuchegg)


Lesenswert?

Diese ganze Modus Umschalterei ist nicht zweckdienlich.
Vor allen Dingenspiegelt es nicht das wieder, was am LCD passiert.

Das LCD kennt Kommandos und anzuzeigende (oder eben in diesem Fall ins 
DDRAM auszugebende) Daten. Das ist alles. Das ist die ganze 
Unterschiedung: Das nächste ans LCD übertragene Byte, ist das vom LCD 
als Kommando aufzufassen oder ist das als Datenbyte aufzufassen.

D.h. vernünftigerweise macht man sich 2 Ausgabefunktionen. Die eine, die 
ein Kommandobyte ausgibt und die andere, die ein Datenbyte ausgibt. Die 
beiden Funktionen unterscheiden sich nur in der Behandlung der RS 
Leitung.

Die Home Funktion, die ja naturgemäss ein Kommando ausgibt, sieht dann 
so aus
1
void lcd_home() {
2
  lcd_write_command( 0x02 );
3
  delay_ms(50);
4
}
und auch andere Funktionen, die dem LCD einen Befehl übermitteln, 
benutzten die lcd_write_command Funktion.

Die lcd_write_data Funktion wird immer dann benutzt, wenn eben ein 
Datenbyte (also KEIN Kommando) auszugeben ist.

Dann kommt man auch nicht mit diversen Modusumschaltungen durcheinander, 
die man eingeführt hat, obwohl es keine Notwendigkeit dafür gibt. Es ist 
immer klar, ob ein Kommando ans LCD zu übermitteln ist, oder ob es sich 
um Daten handelt.

von Nino K. (lnino)


Lesenswert?

Um den Code etwas übersichtlicher zu gestalten habe ich nun versucht 
anhand der Arduino Lib (LiquidCrystal) eine Funktion in meine Nerdkit 
LCD Lib einzubauen.

Aber ich bekomme am Display immer nur ein komplett ausgefülltes Rechteck 
zu sehen.

Was mache ich hier falsch?

Anbei die neue Funktion in meiner Nerdkit LCD Lib:
1
void lcd_createChar(uint8_t location, uint8_t charmap[]) {
2
  int i = 0;
3
  location &= 0x7;        // 8 possible characters regarding to 1Byte availability
4
  lcd_set_type_command();    // Change into command mode
5
  lcd_write_byte(0x40 | (location << 3));
6
  lcd_set_type_data();      // Change into data mode
7
  
8
  for (i=0; i<8; i++) {
9
  lcd_write_byte(charmap[i]);
10
  }
11
  
12
  lcd_set_type_command();    // Change into command mode
13
  lcd_write_byte(0x80);      // Change to DDRAM
14
  lcd_set_type_data();      // Change into data mode
15
}

Und hier der Quellcode vom Hauptprogramm:
1
#define F_CPU 14745600
2
 
3
#include <stdio.h>
4
 
5
#include <avr/io.h>
6
#include <avr/pgmspace.h>
7
#include <inttypes.h>
8
 
9
#include <inttypes.h>
10
#include <string.h>
11
 
12
#include <util/delay.h>
13
#include "../libnerdkits/delay.h"
14
#include "../libnerdkits/lcd.h"
15
16
uint8_t p1[8] = {0,14,31,31,31,14,0,0};
17
18
int main(void) {
19
20
  // fire up the LCD
21
  lcd_init();
22
  lcd_home();
23
24
lcd_createChar(0, p1);    // Create Char on position 0x00
25
26
lcd_write_byte(0x00);       // Show stored custom character on lcd screen
27
28
  // busy loop
29
  while(1) {
30
31
  // do nothing
32
  }
33
34
  return 0;
35
}

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.