- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: LCD Display (KS0073) in 4 Bit-Modus initialisieren und ansteuern

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2010
    Ort
    Im Städtedreieck Köln-Bonn-Aachen
    Alter
    37
    Beiträge
    106

    Frage LCD Display (KS0073) in 4 Bit-Modus initialisieren und ansteuern

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Guten Abend Community,

    ich bin mal wieder am einen C-Code am verzweifeln.

    Ich versuche ein LCD Display (KS0073, 4 Zeilen je 20 Zeichen) im 4 Bit-Modus betreiben.

    Dabei ist das Display am PORTD von einem ATmega 8 Controller angeschlossen:
    • Datenleitung D0-D3 an Pin D0-D3
    • RS an Pin D4
    • RW an Pin D5
    • Enable an Pin D6


    Ich versuche ohne Fremdbibliothek auszukommen, damit der Lerneffekt möglichs hoch sein soll.
    Habe mir natürlich die "fertigen" Ideen von Peter Fleury angeschaut, wie er es macht (Aber nicht getestet ob diese Bib. bei mir laufen).

    Dabei ist mir beim Initialisieren schon was auf gefallen:
    In der Bib. von Peter Fleury wird das Display 3 mal einen Reset unterzogen:
    Code:
    /* reset LCD */
        delay(16000);                           /* wait 16ms after power-on     */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                   
        delay(4992);                            /* wait 5ms                     */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                 
        delay(64);                              /* wait 64us                    */
        lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                
        delay(64);                              /* wait 64us                    */
    Aber laut Datenblatt des KS0073 wird der 4 Bit-Modus so Initialisiert (mein Code):
    Code:
    _delay_ms(50);    // Nachdem die Versorgungsspannung anliegt, braucht das Display min. 20ms bis es bereit ist. Hier sicherheits halber 50ms.
        LCD_cmd(0x33);    // 2x Softreset (?).
        LCD_cmd(0x32);    // 1x Softreset, da nach auf 4Bit Modus.
        LCD_cmd(0x2C);    // Erweitertes Funktionsregister freischalten.
        LCD_cmd(0x09);    // Erweitertes Funktionsregister: 4 Zeilen aktivieren.
        LCD_cmd(0x28);    // Erweitertes Funktionsregister sperren.
        LCD_cmd(0x0C);    // Display einschalten, Cursor aus, Blinken aus.
        LCD_cmd(0x01);    // Display löschen.
        _delay_ms(1.6);    // Befehl Display löschen dauert länger als andere Befehle.
        LCD_cmd(0x06);    // Display fertig machen. => Initialisierung ist beendet.
    Die LCD_cmd Funktion sieht so aus:
    Code:
    void LCD_cmd(uint8_t data)
    {
        uint8_t data_L, data_H;
        
        data_L=data&0x0F;    // Datenbyte erzeugen b0000.xxxx
        data_H=data>>4;    // Datenbyte erzeugen b0000.xxxx
        
        LCD_PORT=data_H;    // Erst das höhere Nibbel auf die Daten-Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT&=~(1<<LCD_RS_PIN);    // RS-Pin auf low für Kommando Byte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
        LCD_PORT=data_L;    // Das niedrigere Nibbel auf die Daten_Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT&=~(1<<LCD_RS_PIN);    // RS-Pin auf low für Kommando Byte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
    }
    
    void LCD_enable()
    {
        LCD_PORT|=(1<<LCD_E_PIN);
        _delay_us(50);
        LCD_PORT&=~(1<<LCD_E_PIN);
    }
    Das Fragezeichen in der Init stellt meine erste Frage da: Warum muss ich das Display 3x zurücksetzten? Im Datenblatt habe ich nichts gefunden (s. 59 steht die Init für 4Bit), oder überlesen.

    Das ist die eine Frage... Mittlerweile wird das Display über die oben genannte Funktion initialisiert.

    Und nun das wo ich im Moment scheiter:
    Code:
        // Begrüßng schreiben
        LCD_zeichen('I');
        LCD_zeichen('c');
    Die Funktion dazu:
    Code:
    void LCD_zeichen(uint8_t data)
    {
        uint8_t data_L, data_H;
        
        data_H=data>>4;
        data_H=data_H&0x0F;    // Datenbyte erzeugen b0000.xxxx
        data_L=data&0x0F;    // Datenbyte erzeugen b0000.xxxx
        
        LCD_PORT=data_L;    // Erst das höhere Nibbel auf die Daten-Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT|=(1<<LCD_RS_PIN);    // RS-Pin auf high für DatenByte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
        LCD_PORT=data_H;    // Das niedrigere Nibbel auf die Daten_Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT|=(1<<LCD_RS_PIN);    // RS-Pin auf high für DatenByte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
    }
    Was ist mir aufgefallen:
    1. Das ich hier die Nibbels umgekehrt senden muss wie bei den Kommandos ( Bei Kommandos erst High-Nibbel, dann Low-Nobbel. Beim Zeichenschreiben erst Low-Nibbel, dann High-Nibbel).
    2. Wenn ich das 'I' alleine schreie, wird es richtig dargestellt. Kommen mehre Buchstaben dazu gibt es Buchstabensalat.


    Warum? Wo ist mein Denkfehler, oder habe ich das Display falsch initialisiert?

    Vollständigkeitshalber mal den Kompletten C-Code von mir:
    Code:
    /*
     * BMA020.c
     *
     *
     * Created: 26.01.2014 14:28:04
     *  Author: Jimmy
     *
     * Pin Konfiguration:
     *** PC 4: SDA
     *** PC 5: SCL
     ***
     *** PD0-PD3: Daten LCD-Display
     *** PD4: RS LCD-Display
     *** PD5: RW LCD-Display
     *** PD6: Enable (freigabe)
     */ 
    #include <avr/io.h>
    #include <stdlib.h>
    
    #define F_CPU 8000000UL
    #include <util/delay.h>
    
    // ****** Port D umbezeichen ******
    #define LCD_PORT PORTD    // Port D ist nun LCD_PORT
    #define LCD_data0_PIN PD0    // Pin D0 ist nun LCD_data0_PIN
    #define LCD_data1_PIN PD1    // Pin D1 ist nun LCD_data1_PIN
    #define LCD_data2_PIN PD2    // Pin D2 ist nun LCD_data2_PIN
    #define LCD_data3_PIN PD3    // Pin D3 ist nun LCD_data3_PIN
    #define LCD_RS_PIN PD4    // Pin D4 ist nun LCD_RS_PIN
    #define LCD_RW_PIN PD5    // Pin D5 ist nun LCD_RW_PIN
    #define LCD_E_PIN PD6    // Pin D6 ist nun LCD_E_PIN
    
    int16_t poti_wert, x, x_LSB, y, y_LSB, z, z_LSB;
    
    //****** LCD Display Enable Kommando ******
    void LCD_enable()
    {
        LCD_PORT|=(1<<LCD_E_PIN);
        _delay_us(50);
        LCD_PORT&=~(1<<LCD_E_PIN);
    }
    
    //****** Kommandos für LCD Display ******
    void LCD_cmd(uint8_t data)
    {
        uint8_t data_L, data_H;
        
        data_L=data&0x0F;    // Datenbyte erzeugen b0000.xxxx
        data_H=data>>4;    // Datenbyte erzeugen b0000.xxxx
        
        LCD_PORT=data_H;    // Erst das höhere Nibbel auf die Daten-Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT&=~(1<<LCD_RS_PIN);    // RS-Pin auf low für Kommando Byte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
        LCD_PORT=data_L;    // Das niedrigere Nibbel auf die Daten_Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT&=~(1<<LCD_RS_PIN);    // RS-Pin auf low für Kommando Byte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
    }
    
    //****** LCD Display initialisieren ******
    void LCD_init(void)
    {
        _delay_ms(50);    // Nachdem die Versorgungsspannung anliegt, braucht das Display min. 20ms bis es bereit ist. Hier sicherheits halber 50ms.
        LCD_cmd(0x33);    // 2x Softreset (?).
        LCD_cmd(0x32);    // 1x Softreset, da nach auf 4Bit Modus.
        LCD_cmd(0x2C);    // Erweitertes Funktionsregister freischalten.
        LCD_cmd(0x09);    // Erweitertes Funktionsregister: 4 Zeilen aktivieren.
        LCD_cmd(0x28);    // Erweitertes Funktionsregister sperren.
        LCD_cmd(0x0C);    // Display einschalten, Cursor aus, Blinken aus.
        LCD_cmd(0x01);    // Display löschen.
        _delay_ms(1.6);    // Befehl Display löschen dauert länger als andere Befehle.
        LCD_cmd(0x06);    // Display fertig machen. => Initialisierung ist beendet.
    }
    
    //****** Zeichen im Display ausgeben ******
    void LCD_zeichen(uint8_t data)
    {
        uint8_t data_L, data_H;
        
        data_H=data>>4;
        data_H=data_H&0x0F;    // Datenbyte erzeugen b0000.xxxx
        data_L=data&0x0F;    // Datenbyte erzeugen b0000.xxxx
        
        LCD_PORT=data_L;    // Erst das höhere Nibbel auf die Daten-Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT|=(1<<LCD_RS_PIN);    // RS-Pin auf high für DatenByte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
        LCD_PORT=data_H;    // Das niedrigere Nibbel auf die Daten_Pins legen.
        LCD_PORT&=~(1<<LCD_RW_PIN);    // RW-Pin auf low für Schreibzugriff.
        LCD_PORT|=(1<<LCD_RS_PIN);    // RS-Pin auf high für DatenByte.
        LCD_enable();    // LCD Display signalisieren, dass Datenbyte abgeholte werden kann.
    }
    
    //****** Hauptfunktion ******
    int main(void)
    {
        
        // Portrichtung
        DDRD=0xFF;
        DDRB=0x01;
        
        //Display initialisieren  
        LCD_init();
        
        // Begrüßng schreiben
        LCD_zeichen('I');
        LCD_zeichen('C');
            
        while(1)
        {
            PORTB=0x01; // Den Controller beschäftigen
        }
    }
    Zum vergleich, die Bib von Peter Fleury im Anhang

    Hoffe ihr könnt mir weiter helfen.
    Angehängte Dateien Angehängte Dateien
    • Dateityp: pdf ks0073.pdf (673,7 KB, 16x aufgerufen)
    • Dateityp: c lcd.c (21,1 KB, 9x aufgerufen)
    • Dateityp: h lcd.h (10,9 KB, 5x aufgerufen)

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Zitat Zitat von Jimmybot Beitrag anzeigen
    In der Bib. von Peter Fleury wird das Display 3 mal einen Reset unterzogen
    Das ist typisch für LCD-Controller vom Typ HD44780 oder kompatible Controller.
    Im Datenblatt zum KS0073 habe ich derlei nicht gesehen. Der scheint nicht ansatzweise mit dem HD44780 kompatibel zu sein.
    Sicher, dass die Lib von Peter Fleury auch zu deinem Display passt???

    Zitat Zitat von Jimmybot Beitrag anzeigen
    Was ist mir aufgefallen:
    1. Das ich hier die Nibbels umgekehrt senden muss wie bei den Kommandos ( Bei Kommandos erst High-Nibbel, dann Low-Nobbel. Beim Zeichenschreiben erst Low-Nibbel, dann High-Nibbel).


    Davon habe ich im Datenblatt nichts gelesen, stattdessen: Erst das HighNibble, dann das LowNibble.

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.684
    ... LCD Display (KS0073... 4 Bit-Modus ... auf gefallen ... Peter Fleury ... Display 3 mal einen Reset unterzogen ...
    Tja - war mir nie aufgefallen, ich nutzte vor Jahren die Bibliothek von PFleury. Du musst den Code aber richtig lesen: der dreimalige Reset ist nicht für die nibbelweise Übertragung, da steht (in meiner jahrealten) Bibliothek von PFleury ein #if ... #else ... #endif davor. Für den 4bittigen IO sah ich nie einen Mehrfachreset. Und in Deinem ersten Codefenster steht ja auch mehrfach:
    Code:
    /* function set: 8bit interface */
    Versuchs die Bibliothek noch mal aufmerksamen durchzulesen.
    Ciao sagt der JoeamBerg

  4. #4
    Erfahrener Benutzer Roboter-Spezialist Avatar von schorsch_76
    Registriert seit
    25.03.2012
    Ort
    Kurz vor Neuschwanstein
    Alter
    48
    Beiträge
    456
    Ich have vor zwei Wochen einen Ks0073 in Betrieb genommen... Über i2c. Ohne irgendwelche Libs. Ich kann dir in ein paar Stunden dann die Initialisierungsroutine , bzw. Die Sequenz zeigen.
    Gruß Georg

  5. #5
    Erfahrener Benutzer Roboter-Spezialist Avatar von schorsch_76
    Registriert seit
    25.03.2012
    Ort
    Kurz vor Neuschwanstein
    Alter
    48
    Beiträge
    456
    Code:
     // bis in the display state. see PCF8574 in schematic
    // 0: Power
    // 1: RS
    // 2: RW
    // 3: CS (enable)
    // 4: D4
    // 5: D5
    // 6: D6
    // 7: D7
    
           // function set 4 bit
            // this needs to be done without the add_command function
            g_buffer[0] = 0x21;
            g_buffer[1] = 0x21 | (1<<3);
            g_buffer[2] = 0x21;
            twi.write_to_slave(avr::display_address, g_buffer, 3);
            state++;
        case 7:
            return check_twi(state);
        case 8:
            curr_pos = 0;
            add_command(0,0,0x24); // function set line (enable ext. F);
            add_command(0,0,0x09); // set 4 line mode
            add_command(0,0,0x20); // disable extended function again
    
            twi.write_to_slave(avr::display_address, g_buffer, curr_pos);
            state++;
            return false;
        case 9:
            return check_twi(state);
        case 10:
            // init done
            curr_pos = 0;
            add_command(0,0,0x0F); // display on
            add_command(0,0,0x01); // clear display
            add_command(0,0,0x06); // entry mode set
            twi.write_to_slave(avr::display_address, g_buffer, curr_pos);
            state++;
            return false;
    So hab ich mein Display angeschlossen:
    https://www.roboternetz.de/community...l=1#post604859

    add_command macht:
    Code:
    void
    add_command(unsigned char rs, unsigned char rw, unsigned char value)
    {
        unsigned char out = 0x01; // always power
    
        // high nibble
        out |= (value & 0xF0);
    
        // rs and rw flags
        if (rs) out |= (1<<1);
        if (rw) out |= (1<<2);
    
        // toggle e
        out |= (1<<3);
        g_buffer[curr_pos++] = out;
    
        out &= ~(1<<3);
        g_buffer[curr_pos++] = out;
    
        // low nibble
        out &= 0x0F;
        out |= ((value & 0x0F) << 4);
    
        // toggle e
        out |= (1<<3);
        g_buffer[curr_pos++] = out;
    
        out &= ~(1<<3);
        g_buffer[curr_pos++] = out;
    }
    Das bedeutet für dich:
    RS = low / RW = low

    // function set
    - Display D5 hochnehmen
    - E high
    - E low

    // add_command(0,0,0x24) // function set line (enable ext. F);
    - out nibble=2
    - E high
    - E low
    - out nibble=4
    - E high
    - E low

    Du siehst also wie du das umsetzen kannst...

    Das hier ist der Kern meiner Displayroutine.

    Gruß
    Georg

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Für den 4bittigen IO sah ich nie einen Mehrfachreset.
    4-bitiger I/O und Mehrfach-Reset haben auch nichts miteinander zu tun. In der Reset- bzw. frühen Init-Phase der HD44780 gibt es noch keine 4-/8-Bit-Unterscheidung. Die drei gleichen Resetbefehle ist innerhalb ihrer Abfolge unterschiedlicher Zeitbedarf spezifiziert. Da scheint intern verschiedenes zu passieren, was auch die Norwendigkeit des Dreifachresets plausibel macht.
    Sorry, wenn ich jetzt zu ausschweifend gewesen sein sollte.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2010
    Ort
    Im Städtedreieck Köln-Bonn-Aachen
    Alter
    37
    Beiträge
    106
    @ RoboHolIC und oberallgeier:
    der KS0073 ist fast identisch mit dem HD44780, der Unterschied macht sich in der anderen 4-Bit-Inititialisierung bemerkbar.
    Feury hat dies bezüglich seine Bib. angepasst, so dass man es auch für den KS0073 verwenden kann.

    Werde mir heute Abend nochmal den Code von Feury zu gemüte führen...

    @ schorsch: Danke für deinen Code. Werde dann mir auch mal anschauen.

    Ich werde jetzt erstmal euer Input verarbeiten. Danke für euere schnellen Antworten.

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2010
    Ort
    Im Städtedreieck Köln-Bonn-Aachen
    Alter
    37
    Beiträge
    106
    Nachdem es immer noch nicht funktionieren will, bin ich immer noch kein schritt weiter.

    Also habe ich mir gedacht: Alles auf dem Steckbrett platt machen, neu verdrahten und die Bib. von Fleury benutzen....... Ja..... Funktioniert auch nicht. Noch nicht mal das erstellen der Hex File.

    Fehlermeldung:
    3 ld returned 1 exit status
    1 undefined reference to 'lcd_init'
    2 undefined reference to 'lcd_puts'
    hier mein überschaubarer Code:

    Code:
    /*
     * BMA020_LCD.c
     *
     * Created: 10.10.2014 16:26:27
     *  Author: Jimmy
     *
     * - Port B:
     * + PB0: LED grün
     *
     * - Port C:
     * + PC4: SDA
     * + PC5: SCL
     *
     * Pin Konfiguration:
     * - Port D
     * + PD0: Data0
     * + PD1: Data1
     * + PD2: Data2
     * + PD3: Data3
     * + PD4: RS Pin
     * + PD5: RW Pin
     * + PD6: E Pin
     * + PD7: NC
     */ 
    
    
    #include <avr/io.h>
    #include "Bib/lcd.h"
    #define F_CPU 8000000UL
    #include <util/delay.h>
    
    
    
    int main(void)
    {
        // Portrichtung konfigurieren
        DDRB=0x01;
        
        // Initialisierung
        lcd_init(LCD_DISP_ON);
        
        // Begrüßungstext
        lcd_puts("Hallo Unbekannter");
        
        while(1)
        {
            // Den Controller beschäftigen
            PORTB|=(1<<PB0);
        }
    }
    Bin ich so unfähig, oder habe ich einfach nur ein riesen Brett vor meinen Kopf?

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Du solltest doch zuerst die Lib. von Fleury zum laufen bringen, dann weist du das die Hardware funktioniert.
    Aber offensichtlich hast du schon ein Problem beim Compilieren.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  10. #10
    Erfahrener Benutzer Roboter-Spezialist Avatar von schorsch_76
    Registriert seit
    25.03.2012
    Ort
    Kurz vor Neuschwanstein
    Alter
    48
    Beiträge
    456
    Du must das C File der Lib von Fleury in dein Makefile einbinden.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. EADIP204 (KS0073) Display und ° (Grad) Zeichen
    Von cni im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 08.02.2009, 16:42
  2. LCD-Display; 4Bit-Modus immer möglich?
    Von brutzler im Forum AVR Hardwarethemen
    Antworten: 3
    Letzter Beitrag: 29.03.2008, 12:03
  3. Problem 4-zeiliges Display im 4-bit modus!! gelöst!!
    Von zumgwadrad im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 22.11.2006, 17:24
  4. LCD im 8-Bit Modus ansteuern.
    Von michi73 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 18.11.2005, 20:22
  5. LCD - initialisieren im 4-Bit Modus
    Von henne im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 12.03.2005, 01:26

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen