- LiFePO4 Speicher Test         
Ergebnis 1 bis 7 von 7

Thema: Problem mit 4x20 LCD am Atmega88

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied Avatar von High Light
    Registriert seit
    21.08.2009
    Ort
    Baden Württemberg
    Beiträge
    142

    Problem mit 4x20 LCD am Atmega88

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,

    ich arbeite gerade das Buch "AVR Hardware und C-Programmierung in der Praxis" von Florian Schäffer durch.
    Jedoch bin ich auf ein Problem gestoßen und zwar wird bei einer Übung ein 4x20 LCD im 4-bit Modus an einem Atmega betrieben.
    Im Buch wird der PORTC verwendet, jedoch benötige ich diesen für eine AD-Wandlung. Somit habe ich den Code auf PortD umgeschrieben und auf den Atmega gebrannt.

    Außer 2 Balken wird nichts angezeigt...kann mir jemand weiter helfen?

    Hier noch der Code:

    lcd-text.c
    Code:
    /* Schreibt Text auf ein angeschlossenes LCD mit Hilfe der eigenen Include-Datei
     *
     * Demonstration verschiedener Zahlenkonvertierungsmoeglichkeiten
     *
     */
    
    #define F_CPU 16000000UL
    
    #include "lcd_tools.c"
    #include <util/delay.h>    
    #include <stdlib.h>        // itoa etc.
    
    int main(void);
     
    int main()
    {
        
        lcd_ini();
        
        
        lcd_gotopos (1,1);
        lcd_writetext ("Herzlich  Willkommen");
        
        lcd_gotopos (4,2);
        lcd_writetext ("CPR by pe-products");
            
        while(1);
    }
    lcd_tools.c
    Code:
    /* LCD Include-Datei
     *
     * Spezielle Version für 4x20 LCD 
     *
     * LCD_CTRL stellt ein, welcher Controllertyp (wichtig für DD-RAM-Adressen)
     * Einige Routinen sind für ein EA DIP204-4 mit KS0073 Controller notwendig, aber auskommentiert
     *
     * Das LCD ist folgendermaßen angeschlossen:
     * PC4     = RS
     * PC5     = Enable
     * PC0-PC3 = D4-D7
     * R/W ist n.c.
     *
     *
     */
    
    #include <avr/io.h>
    #include <util/delay.h>  
    #include "lcd_tools.h"         
    
    #define LCD_CTRL 0         // (0 = HD44780, 1= KS0073)
    #define delay(us)  _delay_loop_2 (((F_CPU/4000)*us)/1000)        // wartet µs
    
    /**
        @brief    wartet Millisekunden
        @param    Zeit in Millisekunden
        @return    none
    */
    void delay_ms(uint16_t ms)
    {
      for(uint16_t t=0; t<=ms; t++)
        _delay_ms(1); 
    }
    
    /**
        Enable Leitung togglen
    */
    void lcd_flash_e ()
    {
        PORTD = PORTD | ( 1<<DDD5 ) ;        // Enable = HIGH
        delay(100);                            // kurz warten, damit Flanke entsteht
        PORTD = PORTD & ~( 1<<DDD5 ) ;        // Enable = LOW
        delay(100);                            // Warten, bis der durch Enable angelegte Befehl hoffentlich verarbeitet wurde
    }
    
    /**
        @brief    Kommando oder Zeichen an Display senden: 
        @param     rs=0 => Kommando, rs=1 => Zeichen
        @return    none
    */
    void lcd_write (uint8_t data, uint8_t rs)   
    {
        uint8_t dataBits ;
      
        if (rs)                    // write data (RS=1, RW=0) 
           dataBits=0x10;        // RS liegt an Pin 4 = B 0001 0000 = H 10
        else                     // write instruction (RS=0, RW=0) 
           dataBits=0;             
        
        PORTD = dataBits | (data>>4);        // output high nibble first, zzgl. Zustand für RS-Leitung
        lcd_flash_e ();    
    
        PORTD = dataBits | (data&0x0F);        // output low nibble, zzgl. RS-Leitung
        lcd_flash_e ();
    }
    
    /**
        @brief    Display loeschen
        @param     none
        @return    none
    */
    void lcd_cls ()   
    {
        lcd_write(0x00,0);       // B 0000 0000 => Clear
        delay(4000);            // dauert eine Weile
        lcd_write(0x01,0);       // B 0000 0001 => Cursor Home
        delay(4000);            // dauert eine Weile, Wert ausprobiert
    }
    
    /**
        @brief    Zeichenausgabe
        @param     none
        @return    none
    */
    void lcd_writechar ( char zeichen)   
    {
      lcd_write (zeichen, 1);   
    }
    
    /**
        @brief    gibt eine Zeichenkette auf dem LCD aus
        @param     none
        @return    none
    */
    void lcd_writetext ( char *text)    
    {
      uint8_t i = 0;
      while (text[i]!=0) 
      {
        lcd_writechar(text[i]);
        i++;
      }
    }
    
    /**
        @brief    Zeilenwechsel
        @param     none
        @return    none
    */
    void lcd_gotoline (uint8_t zeile)    
    {
        if (LCD_CTRL == 0)
        {
            if (zeile == 1) lcd_write(0x80,0);           // B 1000 0000 => DD-RAM Adress Set 1. Zeile/1.Spalte 
            if (zeile == 2) lcd_write(0x80+0x40,0);       // B 1010 0000 => DD-RAM Adress Set 2. Zeile/1.Spalte 
            if (zeile == 3) lcd_write(0x80+0x14,0);       // B 1010 0000 => DD-RAM Adress Set 3. Zeile/1.Spalte 
            if (zeile == 4) lcd_write(0x80+0x54,0);       // B 1010 0000 => DD-RAM Adress Set 4. Zeile/1.Spalte 
        }
        else
        {
            if (zeile == 1) lcd_write(0x80,0);           // B 1000 0000 => DD-RAM Adress Set 1. Zeile/1.Spalte 
            if (zeile == 2) lcd_write(0x80+0x20,0);       // B 1010 0000 => DD-RAM Adress Set 2. Zeile/1.Spalte 
            if (zeile == 3) lcd_write(0x80+0x40,0);       // B 1010 0000 => DD-RAM Adress Set 3. Zeile/1.Spalte 
            if (zeile == 4) lcd_write(0x80+0x60,0);       // B 1010 0000 => DD-RAM Adress Set 4. Zeile/1.Spalte 
        }
    
    }
    
    /**
        @brief    Cursorpositionieren 
        @param     Zeile, Spalte
        @return    none
    */
    void lcd_gotopos (uint8_t zeile, uint8_t spalte)    
    {
        if (LCD_CTRL == 0)
        {
            if (zeile == 1) lcd_write(0x80+0x00+spalte-1,0);   // DD-RAM Adress 1. Zeile + Spalte
            if (zeile == 2) lcd_write(0x80+0x40+spalte-1,0);   // DD-RAM Adress 2. Zeile + Spalte 
            if (zeile == 3) lcd_write(0x80+0x14+spalte-1,0);   // DD-RAM Adress 3. Zeile + Spalte 
            if (zeile == 4) lcd_write(0x80+0x54+spalte-1,0);   // DD-RAM Adress 4. Zeile + Spalte 
        }
        else
        {
            if (zeile == 1) lcd_write(0x80+0x00+spalte-1,0);   // DD-RAM Adress 1. Zeile + Spalte
            if (zeile == 2) lcd_write(0x80+0x20+spalte-1,0);   // DD-RAM Adress 2. Zeile + Spalte 
            if (zeile == 3) lcd_write(0x80+0x40+spalte-1,0);   // DD-RAM Adress 3. Zeile + Spalte 
            if (zeile == 4) lcd_write(0x80+0x60+spalte-1,0);   // DD-RAM Adress 4. Zeile + Spalte 
        }
    }
    
    /**
        @brief    gibt eine int-Zahl auf dem Display aus. Integriert, damit auf string.h verzichtet werden kann
        @param     Zahl
                Anzahl der Stellen (führende Leerzeichen)
                space=0 => führende Nullen, 1 => führende Leerzeichen
        @return    none
    */
    void lcd_writezahl (int32_t zahl, uint8_t pos, uint8_t spacer)       
    {
       int32_t output;
       char sign = '0';
      
      pos--;       // Korrektur des Parameters für Benutzerfreundlichkeit
      
      if (spacer) sign=' ';
    
      // negatives Vorzeichen oder Leerzeichen
      if (zahl < 0)
      {
        lcd_writechar ('-'); 
        zahl *= -1;        // positive Zahl
      }
    
      output = zahl;
      
      // Hunderttausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender Nullen)
      if (zahl >= 100000) lcd_writechar (0x30 + output/100000); else if (pos >= 5) lcd_writechar (sign);
      output = output % 100000;
    
      // Zehntausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender Nullen)
      if (zahl >= 10000) lcd_writechar (0x30 + output/10000); else if (pos >= 4) lcd_writechar (sign);
      output = output % 10000;
    
      // Tausender-Dezimalstelle oder Leerzeichen
      if (zahl >= 1000) lcd_writechar (0x30 + output/1000); else if (pos >= 3) lcd_writechar (sign);
      output = output % 1000;
    
      // Hunderter-Dezimalstelle oder Leerzeichen
      if (zahl >= 100) lcd_writechar (0x30 + output/100); else if (pos >= 2) lcd_writechar (sign);
      output = output % 100;
    
      // Zehner-Dezimalstelle oder Leerzeichen
      if (zahl >= 10) lcd_writechar (0x30 + output/10); else if (pos >= 1) lcd_writechar (sign);
    
      // einer Dezimalstelle oder Leerzeichen
      lcd_writechar (0x30 + output % 10);
    }
    
    /**
        Zuerst den 8-Bit-Modus aktivieren, Ist wichtig, falls LCD schon im 4-Bit Modus war und dann 
        nach einem Programm-Reset vergeblich versucht würde, den 4-Bit Modus erneut zu aktivieren.
        dann in 4-Bit Modus umschalten.
    */
    void lcd_set4bit ()
    {
       // A C H T U N G ! Diese Initialisierung entspricht nicht den Vorgaben aus dem Datenblatt
    
        PORTD = 0x02;        // B 0000 0010 => in 4-Bit-Modus umschalten 
       lcd_flash_e ();
        delay(5);            
    }
    
    /**
        Portrichtung einstellen. Extern, damit man dies separat aufrufen kann, wenn bspw. LCD schon initialisiert ist und
        per Watchdog ein Reset ausgelöst wurde, man dann aber nicht das Display neu initialisieren möchte, damit es schneller weiter geht
    */
    void lcd_port_ini ()
    {
        DDRD |= 0b00111111;        // setze Portrichtung (1 = Ausgang): 0011 1111 
    }
    
    /**
        @brief    Display initialisieren. Einmal als erstes aufrufen
        @param     none
        @return    none
    */
    void lcd_ini ()
    {
        lcd_port_ini();
     
        delay_ms(15);            // 15ms(40ms) warten bis LCD wirklich bereit! Wir können nicht BUSY auswerten. 
                                // Es gibt Displays die so lange brauchen (z. B. Optrex DMC20481)
    
        lcd_set4bit();            // ab jetzt 4-Bit-Modus
        
    //    lcd_write(0x2C,0);        // 4x20 Spezial: Function Set (0010 1100): 4-Bit, 2 Line, RE-Bit, Dot Scroll, Normal Mode
    //    lcd_write(0x09,0);        // 4x20: Extended Function Set (0000 1001): 5 dot font, Normal Cursor, 4 Line Display
    
        lcd_write(0x28,0);        // B 0010 1000 => Function Set: 4Bit (kein 8-Bit Bus), zweizeiliges Display, 5x7 Dots/Zeichen (kein 5x10), RE-Bit aus
    //    lcd_write(0x0F,0);        // B 0000 1000 => Display On/Off: Display ein, Cursor an, Blinken an
        lcd_write(0x0C,0);        // B 0000 1000 => Display On/Off: Display ein, Cursor aus, Blinken aus
        lcd_write(0x06,0);        // B 0000 0110 => Entry Mode Set: DD-RAM autom. inkr., Cursor bewegen
        
        lcd_cls();                // Display löschen
    }
    Grüße High Light
    __________________________________________________ _____________
    http://pe-products.jimdo.com/

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von robocat
    Registriert seit
    18.07.2006
    Beiträge
    935
    * R/W ist n.c. <--- Hatte ein ähnliches Problem auch schon, lege mal den R/W Pin auf GND.
    Dass Balken angezeigt werden bedeutet, dass die Initialisierung nicht ok ist.

    Grüße

  3. #3
    Erfahrener Benutzer Roboter-Spezialist Avatar von robo_tom_24
    Registriert seit
    04.02.2012
    Ort
    Burgenland, Österreich
    Beiträge
    485
    Kannst du den Originalcode mal auf Port C testen? also nicht dauerhaft, nur um zu sehen ob der Fehler in der Software oder an der Beschaltung liegt

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Zu testen fehlt die lcd_tools.h
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied Avatar von High Light
    Registriert seit
    21.08.2009
    Ort
    Baden Württemberg
    Beiträge
    142
    Also das mit R/W auf GND zu legen hat nicht geklappt.

    Bevor ich den Code für PORTD umgeschrieben habe, habe ich ihn auf dem PORTC getestet und es hat alles geklappt.

    Hier noch die lcd_tools.h :
    Code:
    #include <stdint.h> 
    
    void delay_ms(uint16_t);
    void lcd_flash_e (void);
    void lcd_write (uint8_t, uint8_t);
    void lcd_cls (void);
    void lcd_writechar (char);
    void lcd_writetext (char *);
    void lcd_gotoline (uint8_t);
    void lcd_gotopos (uint8_t, uint8_t);
    void lcd_writezahl (int32_t, uint8_t, uint8_t);
    void lcd_set4bit (void);
    void lcd_port_ini (void);
    void lcd_ini (void);
    __________________________________________________ _____________
    http://pe-products.jimdo.com/

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Ich habe nur ein 2-Zeiliges Disp, aber es wird initialisiert und Herzlich Willko steht auch drinnen.
    Der Code scheint also zu passen.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied Avatar von High Light
    Registriert seit
    21.08.2009
    Ort
    Baden Württemberg
    Beiträge
    142
    Hallo zusammen,

    ich habe das Problem heraus gefunden. Das Problem lag nicht an der Software, sondern an der Hardware... *PEINLICH*

    Trotzdem nochmal Danke für die Hilfe.

    Grüße High Light
    __________________________________________________ _____________
    http://pe-products.jimdo.com/

Ähnliche Themen

  1. Schon wieder ein 4x20 LCD-Problem
    Von masterx im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 08.03.2011, 18:32
  2. atmega88 Fusebit Problem, avrdude hängt sich auf.
    Von hunni im Forum AVR Hardwarethemen
    Antworten: 6
    Letzter Beitrag: 01.09.2010, 11:24
  3. ATmega88 avrdude problem
    Von Morpheus2001 im Forum AVR Hardwarethemen
    Antworten: 5
    Letzter Beitrag: 14.11.2007, 19:41
  4. 4x20 LCD und Peter Fleury
    Von hansbausn im Forum C - Programmierung (GCC u.a.)
    Antworten: 11
    Letzter Beitrag: 27.01.2006, 17:06
  5. Bibliothek für 4x20 LCD
    Von Felix G im Forum C - Programmierung (GCC u.a.)
    Antworten: 7
    Letzter Beitrag: 03.01.2005, 00:01

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad