Forum: Mikrocontroller und Digitale Elektronik LCD Library 16x4 mit AVR Mega32


von Stephan (Gast)


Lesenswert?

Guten Morgen,

seit einigen Stunden versuche ich bereits die LCD Library von Peter 
Fleury in mein AVR Programm einzubinden. Ich habe die Anpassung 
entsprechend dem Datenblatt vorgenommen und das Übersetzen und Laden in 
den Mega ist auch kein Problem.
Leider funktionert das Display überhaupt nicht. Ein hardwareseitiger 
Fehler kann ausgeschlossen werden, da mit Bascom keine Probleme 
auftreten.
Nach dem Laden des hex-Files wird nur die erste Zeile initialisiert, 
also die erste und dritte Zeile im Display sind völlig schwarz...
Vielleicht habt ihr eine Idee, wo der Fehler liegen könnte. Mein 
Programm sieht folgendermaßen aus:

aus der "lcd.h":
1
#define LCD_CONTROLLER_KS0073 0  //Use 0 for HD44780 controller, 1 for KS0073 controller */
2
3
/** 
4
 *  @name  Definitions for Display Size 
5
 *  Change these definitions to adapt setting to your display
6
 */
7
#define LCD_LINES           4     /**< number of visible lines of the display */
8
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
9
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
10
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
11
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
12
#define LCD_START_LINE3  0x10     /**< DDRAM address of first char of line 3 */
13
#define LCD_START_LINE4  0x50     /**< DDRAM address of first char of line 4 */
14
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
15
16
17
#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
18
#if LCD_IO_MODE
19
/**
20
 *  @name Definitions for 4-bit IO mode
21
 *  Change LCD_PORT if you want to use a different port for the LCD pins.
22
 *
23
 *  The four LCD data lines and the three control lines RS, RW, E can be on the 
24
 *  same port or on different ports. 
25
 *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
26
 *  different ports. 
27
 *
28
 *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
29
 *  is possible to connect these data lines in different order or even on different
30
 *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
31
 *  
32
 */
33
#define LCD_PORT         PORTA        /**< port for the LCD lines   */
34
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
35
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
36
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
37
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
38
#define LCD_DATA0_PIN    3            /**< pin for 4bit data bit 0  */
39
#define LCD_DATA1_PIN    2            /**< pin for 4bit data bit 1  */
40
#define LCD_DATA2_PIN    1            /**< pin for 4bit data bit 2  */
41
#define LCD_DATA3_PIN    0            /**< pin for 4bit data bit 3  */
42
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
43
#define LCD_RS_PIN       5            /**< pin  for RS line         */
44
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
45
#define LCD_RW_PIN       6           /**< pin  for RW line         */
46
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
47
#define LCD_E_PIN        4            /**< pin  for Enable line     */

Das Einbinden in das Hauptprogramm habe ich folgendermaßen gestaltet:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#include "i2cmaster.h"
5
#include "lcd.h"
6
7
#define Wzeit 0xA0
8
#define Rzeit 0xA1
9
#define T_wr 0x40
10
#define T_rd 0x41
11
#define T_wr1 0x42
12
#define T_rd1 0x43
13
#define Komp 0xC0
14
#define Kompw 0xC1
15
16
17
18
19
20
21
int main(void)
22
{
23
  i2c_init();
24
25
  
26
27
  //Initialisierung der Tastatur
28
  i2c_start(T_wr+I2C_WRITE);
29
  i2c_write(255);
30
  i2c_stop();
31
32
  //Initialisierung der Temperaturfühler
33
  i2c_start(0x90+I2C_WRITE);
34
  i2c_write(172);
35
  i2c_stop();
36
37
  i2c_start(0x90+I2C_WRITE);
38
  i2c_write(238);
39
  i2c_stop();
40
41
  i2c_start(0x92+I2C_WRITE);
42
  i2c_write(172);
43
  i2c_stop();
44
45
  i2c_start(0x92+I2C_WRITE);
46
  i2c_write(238);
47
  i2c_stop();
48
49
50
  //Initialisierung LCD Modul
51
  lcd_init(LCD_DISP_ON);
52
53
54
  
55
56
57
  for(;;)
58
  {
59
  
60
  lcd_gotoxy(1,1);
61
  lcd_puts("Test");
62
63
64
  }
65
66
67
return (0);  
68
69
}

Viele Grüße

Stephan

von Benedikt Patt (Gast)


Lesenswert?

Hi,

benutzt du in Bascom auch den 4-Bit Modus??

Gruß
Benedikt

von Stephan (Gast)


Lesenswert?

ja, in Bascom verwende ich auch den 4-Bit Modus

von Frank G. (dg1sbg)


Angehängte Dateien:

Lesenswert?

Stephan wrote:

> aus der "lcd.h":
> #define LCD_LINE_LENGTH  0x40     /**< internal line length of the
> display    */

Wirklich 64 Zeichen pro Zeile im LCD Buffer?

> #define LCD_START_LINE1  0x00     /**< DDRAM address of first char of
> line 1 */
> #define LCD_START_LINE2  0x40     /**< DDRAM address of first char of
> line 2 */
> #define LCD_START_LINE3  0x10     /**< DDRAM address of first char of
> line 3 */
> #define LCD_START_LINE4  0x50     /**< DDRAM address of first char of
> line 4 */

Passt das zu Deinem LCD Controller ?

> #define LCD_DATA0_PIN    3            /**< pin for 4bit data bit 0  */
> #define LCD_DATA1_PIN    2            /**< pin for 4bit data bit 1  */
> #define LCD_DATA2_PIN    1            /**< pin for 4bit data bit 2  */
> #define LCD_DATA3_PIN    0            /**< pin for 4bit data bit 3  */

Wirklich "verkehrt herum" ?

Ich frag so, weil ich genau dort auch Probleme hatte ... Wenn Dir eine 
einfachere Version lieber ist zum Debuggen, schau mal im Dateianhang ...

Gruß,
   Frank

von Stephan M. (stmiko)


Lesenswert?

Hallo Frank,

mit den 64 Zeichen ergibt sich doch aus 16x4 oder sehe ich das falsch?
Adressen des ersten Zeichen der jeweiligen Zeile habe ich aus dem 
Datenblatt und sollten stimmen.

Das Display ist wie folgt an den Controller angeschlossen:

DB4  A03
DB5  A02
DB6  A01
DB7  A00

RS   A05
R/W  A06
E    A04

bin mit der Reihenfolge in der Headerdatei nicht ganz sicher... Ich habe 
die Reihenfolge auch schon geändert und es hat sich nichts geändert.

von Benedikt Patt (Gast)


Lesenswert?

Hast du auch die CPU Taktfrequenz richtig angegeben?
Sonst stimmen ja die Delays nicht mehr. Das mögen die LCDs auch nicht 
besonders.

von Stephan M. (stmiko)


Lesenswert?

Das habe ich auch angepasst...

von Stephan M. (stmiko)


Lesenswert?

Ich habe den Fehler nun gefunden, bloß noch nicht die richtige Idee 
diesen zu beheben.
Wird der Befehl " lcd_init(LCD_DISP_ON); " aufgerufen, so bleibt der 
Controller an dieser Stelle hängen und nichts passiert mehr...

Hatte dieses Phänomen auch schon mal jemand beobachten können?

von Pete K. (pete77)


Lesenswert?

Ist bei dem 16x4 denn nur ein Controller verbaut ? Ansonsten tippe ich 
mal, dass zwei Enable Leitungen benötigt werden (wie z.B. bei dem Wintek 
Display von Pollin).
Man muss dann abhängig von der Line den richtigen Controller einschalten 
(E1 bei 1+2, E2 bei 3+4).

Angabe der Beschreibung des LCDs wäre hilfreich.

von Stephan M. (stmiko)


Lesenswert?

Laut Datenblatt ist nur ein Controller vorhanden und auch nur eine 
Enable - Leitung!

Das Display hat folgende Bezeichnung:
" NLC - 16x4x05 " und ist mit dem Controller KS0066, welcher dem HD44780 
entspricht, bestückt.

von Pete K. (pete77)


Lesenswert?

Schließ mal das Display mit DB4-A0, DB5-A1 etc. an.

Manchmal hilft es auch, die Timings etwas zu erhöhen.

Bitte poste mal Deine Init-Routine.

von Stephan M. (stmiko)


Lesenswert?

Init stammt von Peter Fleury...
1
void lcd_init(uint8_t dispAttr)
2
{
3
#if LCD_IO_MODE
4
    /*
5
     *  Initialize LCD to 4 bit I/O mode
6
     */
7
     
8
    if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
9
      && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
10
      && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) 
11
      && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
12
    {
13
        /* configure all port bits as output (all LCD lines on same port) */
14
        DDR(LCD_DATA0_PORT) |= 0x7F;
15
    }
16
    else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
17
           && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
18
    {
19
        /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
20
        DDR(LCD_DATA0_PORT) |= 0x0F;
21
        DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
22
        DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
23
        DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
24
    }
25
    else
26
    {
27
        /* configure all port bits as output (LCD data and control lines on different ports */
28
        DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
29
        DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
30
        DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
31
        DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
32
        DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
33
        DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
34
        DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
35
    }
36
    delay(35000);        /* wait 16ms or more after power-on       */
37
    
38
    /* initial write to lcd is 8bit */
39
    LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;
40
    LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;
41
    lcd_e_toggle();
42
    delay(4992);         /* delay, busy flag can't be checked here */
43
   
44
    /* repeat last command */ 
45
    lcd_e_toggle();      
46
    delay(64);           /* delay, busy flag can't be checked here */
47
    
48
    /* repeat last command a third time */
49
    lcd_e_toggle();      
50
    delay(64);           /* delay, busy flag can't be checked here */
51
52
    /* now configure for 4bit mode */
53
    LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4
54
    lcd_e_toggle();
55
    delay(64);           /* some displays need this additional delay */

Ich habe noch ein wenig im Netz weiter rumgeschaut und habe entdeckt, 
dass der KS0066 scheinbar nicht mit der Library funktioniert. Deshalb 
werde ich wohl selber eine Library schreiben müssen :-(

von holger (Gast)


Lesenswert?

>Wird der Befehl " lcd_init(LCD_DISP_ON); " aufgerufen, so bleibt der
>Controller an dieser Stelle hängen und nichts passiert mehr...

Dann bleibt er vermutlich beim Busycheck hängen.
Programm passt möglicherweise nicht mit der
realen Verdrahtung zusammen.

von Benedikt Patt (Gast)


Lesenswert?

Ich habe die Library aktuell mit einem 4 x 20 Zeichen LCD von Reichelt 
am Laufen. Das Teil hat laut Datenblatt den KS0066U. Das funktioniert 
einwandfrei.

Gruß
Benedikt

von Stephan M. (stmiko)


Lesenswert?

Hallo Benedikt,

schicke mir doch mal bitte die Header-Datei, welche du konfiguriert 
hast. Vielleicht kann ich den entscheiden Unterschied finden. Es muss 
mit der Adressierung der verschieden Kommandos zusammenhängen, eine 
andere Idee habe ich langsam nicht mehr...

von Benedikt Patt (Gast)


Lesenswert?

So, hier ist meine Header Datei (zumindest der relevante Ausschnitt, am 
Rest habe ich nichts verändert):
1
/* 
2
 *  @name  Definitions for MCU Clock Frequency
3
 *  Adapt the MCU clock frequency in Hz to your target. 
4
 */
5
#define XTAL F_CPU              /**< clock frequency in Hz, used to calculate delay timer */
6
7
/*
8
 * @name  Definition for LCD controller type
9
 * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.
10
 */
11
#define LCD_CONTROLLER_KS0073 0  /**< Use 0 for HD44780 controller, 1 for KS0073 controller */
12
13
/* 
14
 *  @name  Definitions for Display Size 
15
 *  Change these definitions to adapt setting to your display
16
 */
17
#define LCD_LINES           4     /**< number of visible lines of the display */
18
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
19
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
20
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
21
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
22
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
23
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
24
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
25
26
27
#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
28
#if LCD_IO_MODE
29
/**
30
 *  @name Definitions for 4-bit IO mode
31
 *  Change LCD_PORT if you want to use a different port for the LCD pins.
32
 *
33
 *  The four LCD data lines and the three control lines RS, RW, E can be on the 
34
 *  same port or on different ports. 
35
 *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
36
 *  different ports. 
37
 *
38
 *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
39
 *  is possible to connect these data lines in different order or even on different
40
 *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
41
 *  
42
 */
43
#define LCD_PORT         PORTC        /**< port for the LCD lines   */
44
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
45
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
46
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
47
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
48
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
49
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
50
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
51
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
52
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
53
#define LCD_RS_PIN       4            /**< pin  for RS line         */
54
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
55
#define LCD_RW_PIN       5            /**< pin  for RW line         */
56
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
57
#define LCD_E_PIN        6            /**< pin  for Enable line     */

Abgesehen von den Adressen und der Pin-Belegung sieht das deiner Header 
Datei ja recht ähnlich.
Ich habe die restlichen Data-Pins (0-3) vom Display auf Masse gelegt.

Gruß
Benedikt

von Stephan M. (stmiko)


Lesenswert?

Die Konfiguration deines Displays stimmt auch mit dem in meinem 
Datenblattheft überein. Der einzige Unterschied besteht darin, dass ich 
die anderen Pins nicht auf Masse gelegt habe, denkst du, dass das die 
Ursache sein könnte?

von Stephan M. (stmiko)


Lesenswert?

Die Pins auf Masse zu legen ist nicht die Lösung, im Datenblatt wird der 
Zustand im 4-Bit Modus auch als unrelevant angegeben...

von Benedikt Patt (Gast)


Lesenswert?

Bei anderen Displays habe ich mal die Erfahrung gemacht das es nur geht 
wenn die nicht benötigten Pins auf Masse liegen. Daher mache ich das 
jetzt einfach immer.
Wenn's aber anders im Datenblatt steht wird das wohl stimmen :)

von Pete K. (pete77)


Lesenswert?

In der Init Routine werden nicht die delay.h Routinen benutzt. Das würde 
ich ändern, da die delay.h Routinen Frequenz unabhängig sind (z.B. 
_delay_ms(x)).

Passt in der Init auch das Setzen auf Output (DDR(LCD_DATA0_PORT) |= 
0x7F;) mit der Konfiguration zusammen ? Durch die vielen If's steige ich 
jetzt nicht so schnell durch :-)

von SoLaLa (Gast)


Lesenswert?

hmmm... weiß nicht obs hilft, aber ich hatte vor n paar Tagen mit der 
obigen I2Clib nen Display angesteuert und dabei externe Pullups für SCL 
und SDA verwendet... völlig unerklärliche Abstürze trieben mich zur 
Verzweiflung :-)
Als ich dann die externen Widerstände weggeputzt und statt dessen die 
internen Pullups aktiviert hatte liefs wie am Schnürchen

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.