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