Hallo Forum,
ich muss mal wieder zu Kreuze kriechen und euch um Rat zu einem µC
Problem, genauer zur Ansteuerung eines 2*16 Zeichen LCDs, bitten. Ich
habe hier ein PICDEM 2 Plus Demo Board mit PIC18F4520 und 4MHz Quarz.
Das Problem besteht darin, dass ich nicht die beabsichtigten Zeichen
ausgeben kann. Anstatt eines Buchstaben wird ein Symbol aus zwei
senkrechten Linien dargestellt. Das 5*8 Felder-Symbol hat dann die
zweite und vierte Spalte dunkel, der Rest hell. Bei manchen Zeichen
erscheinen auch drei dunkle Linien, die sind dann in der ersten, dritten
und fünften Spalte.
Ich vermute ein Problem bei der Initialisierung. Muss ich die
Zeichenauswahl im CGROM konfigurieren? Nach LCD Initialisierung kann den
Cursor ins gewünschte Feld verschieben, er blinkt auch wie gewünscht
etc.
Der gesamte Code ist auch angehängt, aber hier das (vermutlich)
wesentliche, so wird mein LCD initialisiert:
1 | void LcdInit(void) {
|
2 | LcdTris = 0x00; // All LCD lines as outputs
|
3 | Lcd_Vcc = 0;
|
4 | Lcd_Vcc = 1;
|
5 |
|
6 | __delay_ms(20);
|
7 | LcdWriteNibble(0x03,1); // transmit 3 times soft reset
|
8 | __delay_ms(20);
|
9 | LcdWriteNibble(0x03,1);
|
10 | __delay_ms(20);
|
11 | LcdWriteNibble(0x03,1);
|
12 | __delay_ms(20);
|
13 | LcdWriteNibble(0x02,1);
|
14 |
|
15 | LcdWait();
|
16 | LcdCommand(0x28); // 4bit interface, 2-line LCD, 5*8 font
|
17 | LcdWait();
|
18 | LcdCommand(0x0F); // Disply ON, Cursor ON, Blinking ON
|
19 | LcdWait();
|
20 | LcdCommand(0x06); // Content fix, cursor posiion incremented
|
21 | LcdWait();
|
22 | LcdCommand(0x02); // Cursor in Start Position
|
23 | LcdWait();
|
24 | LcdClear();
|
25 | }
|
26 |
|
27 | void LcdCommand(unsigned char cmd) {
|
28 | unsigned char tmp;
|
29 | tmp = cmd & 0xF0; // get upper nibble of command byte
|
30 | tmp = tmp >> 4; // shift upper nibble into interface nibble
|
31 | LcdWriteNibble(tmp,1); // send low nibble into cmd register
|
32 | tmp = cmd & 0x0F; // get lower nibble of command byte
|
33 | LcdWriteNibble(tmp,1); // switch on LCD Interface
|
34 | }
|
35 |
|
36 | void LcdWriteNibble(unsigned char Msg, unsigned char CmdSelect) {
|
37 | unsigned char tmp;
|
38 | Lcd_RW = 0; // This is a WRITE operation
|
39 | if (CmdSelect) { // 1 if Cmd
|
40 | Lcd_RS = 0; // Clear for writing in command register
|
41 | } else {
|
42 | Lcd_RS = 1; // 0 if Data
|
43 | }
|
44 | Lcd_E = 1;
|
45 |
|
46 | tmp = LcdLat; // get LATD status
|
47 | tmp &= 0xF0; // clear message lines for new message
|
48 | LcdLat = tmp | (Msg & 0x0F); // Reload LATD with updated message
|
49 | Nop();
|
50 | Nop();
|
51 |
|
52 | Lcd_E = 0;
|
53 | }
|
54 |
|
55 | void LcdWait(void) {
|
56 | unsigned char status;
|
57 | Lcd_RS = 0; // Sending into command register
|
58 | Lcd_RW = 1; // Sending a READ operation
|
59 | do {
|
60 | status = LcdReadByte(); // Read LCD state
|
61 | } while (status & 0x80); // bit 7 is 1 while busy
|
62 | }
|
63 |
|
64 | unsigned char LcdReadByte(void) {
|
65 | unsigned char tmp, res;
|
66 | LcdTris |= 0x0F; // make D3:0 inputs
|
67 | Lcd_E = 1; // Enable LCD interface
|
68 | Nop();
|
69 | Nop();
|
70 | tmp = PORTD; // first read for first nibble
|
71 | Lcd_E = 0; // Disable LCD interface
|
72 | res = tmp << 4; // shift input to high nibble and save
|
73 | Lcd_E = 1; // Enable LCD interfae
|
74 | Nop();
|
75 | Nop();
|
76 | tmp = PORTD; // second read for second nibble
|
77 | Lcd_E = 0; // Disable LCD interface
|
78 | tmp &= 0x0F; // clear upper nibble
|
79 | res |= tmp; // move lower nibble to return result
|
80 | LcdTris &= 0xF0; // make D3:0 outputs
|
81 | return(res);
|
82 | }
|
Und auf diese Art möchte ich ein Zeichen ausgeben:
1 | void LcdPutChar(unsigned char value) {
|
2 | unsigned char tmp;
|
3 | tmp = value & 0xF0; // get upper nibble of character
|
4 | tmp >> 4; // shift upper nibble into data lines
|
5 | LcdWriteNibble(tmp,0);
|
6 | tmp = value & 0x0F; // get lower nibble of character
|
7 | LcdWriteNibble(tmp,0);
|
8 | LcdWait();
|
9 | }
|
10 |
|
11 | void LcdWriteNibble(unsigned char Msg, unsigned char CmdSelect) {
|
12 | unsigned char tmp;
|
13 | Lcd_RW = 0; // This is a WRITE operation
|
14 | if (CmdSelect) { // 1 if Cmd
|
15 | Lcd_RS = 0; // Clear for writing in command register
|
16 | } else {
|
17 | Lcd_RS = 1; // 0 if Data
|
18 | }
|
19 | Lcd_E = 1;
|
20 |
|
21 | tmp = LcdLat; // get LATD status
|
22 | tmp &= 0xF0; // clear message lines for new message
|
23 | LcdLat = tmp | (Msg & 0x0F); // Reload LATD with updated message
|
24 | Nop();
|
25 | Nop();
|
26 |
|
27 | Lcd_E = 0;
|
28 | }
|
Vielleicht sieht jemand von euch einen Fehler? Wenn ihr noch weitere
Infos braucht, kann ich die gerne anbieten.
Viele Grüße und herzlichen Dank,
Ulminpoika