mikrocontroller.net

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


Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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":
#define LCD_CONTROLLER_KS0073 0  //Use 0 for HD44780 controller, 1 for KS0073 controller */

/** 
 *  @name  Definitions for Display Size 
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           4     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#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 */
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */


#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
#if LCD_IO_MODE
/**
 *  @name Definitions for 4-bit IO mode
 *  Change LCD_PORT if you want to use a different port for the LCD pins.
 *
 *  The four LCD data lines and the three control lines RS, RW, E can be on the 
 *  same port or on different ports. 
 *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
 *  different ports. 
 *
 *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
 *  is possible to connect these data lines in different order or even on different
 *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
 *  
 */
#define LCD_PORT         PORTA        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#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  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       5            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       6           /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        4            /**< pin  for Enable line     */  


Das Einbinden in das Hauptprogramm habe ich folgendermaßen gestaltet:
#include <avr/io.h>
#include <util/delay.h>

#include "i2cmaster.h"
#include "lcd.h"

#define Wzeit 0xA0
#define Rzeit 0xA1
#define T_wr 0x40
#define T_rd 0x41
#define T_wr1 0x42
#define T_rd1 0x43
#define Komp 0xC0
#define Kompw 0xC1






int main(void)
{
  i2c_init();

  

  //Initialisierung der Tastatur
  i2c_start(T_wr+I2C_WRITE);
  i2c_write(255);
  i2c_stop();

  //Initialisierung der Temperaturfühler
  i2c_start(0x90+I2C_WRITE);
  i2c_write(172);
  i2c_stop();

  i2c_start(0x90+I2C_WRITE);
  i2c_write(238);
  i2c_stop();

  i2c_start(0x92+I2C_WRITE);
  i2c_write(172);
  i2c_stop();

  i2c_start(0x92+I2C_WRITE);
  i2c_write(238);
  i2c_stop();


  //Initialisierung LCD Modul
  lcd_init(LCD_DISP_ON);


  


  for(;;)
  {
  
  lcd_gotoxy(1,1);
  lcd_puts("Test");


  }


return (0);  

}


Viele Grüße

Stephan

Autor: Benedikt Patt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

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

Gruß
Benedikt

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, in Bascom verwende ich auch den 4-Bit Modus

Autor: Frank Goenninger (dg1sbg)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt Patt (Gast)
Datum:

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

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich auch angepasst...

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Init stammt von Peter Fleury...
void lcd_init(uint8_t dispAttr)
{
#if LCD_IO_MODE
    /*
     *  Initialize LCD to 4 bit I/O mode
     */
     
    if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
      && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
      && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) 
      && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
    {
        /* configure all port bits as output (all LCD lines on same port) */
        DDR(LCD_DATA0_PORT) |= 0x7F;
    }
    else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
           && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
    {
        /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */
        DDR(LCD_DATA0_PORT) |= 0x0F;
        DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
        DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
        DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
    }
    else
    {
        /* configure all port bits as output (LCD data and control lines on different ports */
        DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);
        DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);
        DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);
        DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
        DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
        DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
        DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
    }
    delay(35000);        /* wait 16ms or more after power-on       */
    
    /* initial write to lcd is 8bit */
    LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;
    LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;
    lcd_e_toggle();
    delay(4992);         /* delay, busy flag can't be checked here */
   
    /* repeat last command */ 
    lcd_e_toggle();      
    delay(64);           /* delay, busy flag can't be checked here */
    
    /* repeat last command a third time */
    lcd_e_toggle();      
    delay(64);           /* delay, busy flag can't be checked here */

    /* now configure for 4bit mode */
    LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4
    lcd_e_toggle();
    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 :-(

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt Patt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Benedikt Patt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hier ist meine Header Datei (zumindest der relevante Ausschnitt, am 
Rest habe ich nichts verändert):
/* 
 *  @name  Definitions for MCU Clock Frequency
 *  Adapt the MCU clock frequency in Hz to your target. 
 */
#define XTAL F_CPU              /**< clock frequency in Hz, used to calculate delay timer */

/*
 * @name  Definition for LCD controller type
 * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller.
 */
#define LCD_CONTROLLER_KS0073 0  /**< Use 0 for HD44780 controller, 1 for KS0073 controller */

/* 
 *  @name  Definitions for Display Size 
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           4     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#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  0x14     /**< DDRAM address of first char of line 3 */
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */


#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
#if LCD_IO_MODE
/**
 *  @name Definitions for 4-bit IO mode
 *  Change LCD_PORT if you want to use a different port for the LCD pins.
 *
 *  The four LCD data lines and the three control lines RS, RW, E can be on the 
 *  same port or on different ports. 
 *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
 *  different ports. 
 *
 *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
 *  is possible to connect these data lines in different order or even on different
 *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
 *  
 */
#define LCD_PORT         PORTC        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#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

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stephan M. (stmiko)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Benedikt Patt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: SoLaLa (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.