www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik bringe LCD-Display nicht zum laufen


Autor: Dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo


Ich habe mir kürzlich bei Conrad ein LCD-Display mit 16x2 Zeilen 
gekauft...

Nun bin ich am Programmieren. Ich habe sowohl fertigen Code aus 
verschiedenen Tutorials genommen und die Ports angepasst und ein 
programm mehr oder weniger selber geschrieben.
Doch das einzige was angezeigt wird, sind die 32 Zeichen, aber alle 
davon als schwarze Rechtecke. Also wie wenn man nur den Strom ansteckt.

Was könnte am Code Falsch sein? Ach ja, uC ist ein Atmega168 mit 
internem Takt von 8Mhz und prescaler von 8 --> 1Mhz

hier der Code:
#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000

#define PORT_LCD  PORTD
#define PIN_RS  4
#define PIN_EN  5

#define CLEAR_DISPLAY 0x01
#define CURSOR_HOME 0x02

void lcd_enable(void)
{
  PORT_LCD |= (1<<PIN_EN);
  asm("nop");
  asm("nop");
  asm("nop");
  PORT_LCD &= ~(1<<PIN_EN);
}

void lcd_data(unsigned char temp1)
{
   unsigned char temp2 = temp1;
 
   temp1 = temp1 >> 4;
   temp1 = temp1 & 0x0F;
   PORT_LCD &= 0xF0;
   PORT_LCD |= temp1 | (1<<PIN_RS); // inkl. LCD_RS = RS-Leitung setzen
   lcd_enable();
 
   temp2 = temp2 & 0x0F;
   PORT_LCD &= 0xF0;
   PORT_LCD |= temp2 | (1<<PIN_RS); // inkl. LCD_RS = RS-Leitung setzen
   lcd_enable();
   
   _delay_ms(50.0);
}

void lcd_command(unsigned char temp1)
{
  unsigned char temp2 = temp1;
  
  temp1 = temp1 >> 4; //oberes nibble holen
  temp1 = temp1 & 0x0F; //maskieren
  PORT_LCD = temp1; //setzen
  lcd_enable();
  
  temp2 = temp2 & 0x0F; //unteres nibble holen und maskieren
  PORT_LCD = temp2; //setzen
  lcd_enable();
  
  _delay_ms(5.0);
}

void lcd_init(void)
{
  _delay_ms(20);
  
  PORT_LCD = 0x03;
  lcd_enable();
  _delay_ms(5.0);
  
  PORT_LCD = 0x03;
  lcd_enable();
  _delay_us(160);
  
  PORT_LCD = 0x03;
  lcd_enable();
  _delay_us(160);
  
  PORT_LCD = 0x02;
  lcd_enable();
  _delay_ms(5.0);
  
  lcd_command(0x28);
  
  lcd_command(0x0C);
  
  lcd_command(0x04);
  
  lcd_command(CLEAR_DISPLAY);
  
  lcd_command(CURSOR_HOME);
}

int main(void)
{
  lcd_init();
  
  lcd_data("a");
  
  while(1)
  {
  }
  
  return 0;
}

Vielen Dank, falls mir jemand helfen kann/will, Gruss und schönen Abend
Dave

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beitrag "Wie mache ich eine Textausgabe 8Bit auf Display?"

Ist ausführlich erklärt und am Ende des Threads gibts nen Code zum 
Testen.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal am Kontrastpoti rumgespielt?

Autor: Dave Sommer (applican)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen ;-)

Ich habe nochmals den Code durchgeschaut und auch noch mit dem anderen 
Thread verglichen... Schlussendlich habe ich gemerkt, dass ein Poti doch 
nicht schlecht ist, anstatt einfach auf Ground zu legen (nur schwarze 
Rechtecke und kein Inhalt sichtbar).
Dann hatte ich noch das Problem, dass ich nicht mehr aus dem 
Schreibmodus raus kam, weil das RS-bit nicht wieder auf 0 gesetzt wurde.

aber jetzt geht alles... macht richtig spass, damit zu spiiiielen ;-)

gruss und Danke für die Hilfe!
Dave

Autor: Cosi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

habe ebenfalls ein Prob. und wollte kein neues Thema eröffnen, daher 
poste ich es einfach hier...
Ich kriege es einfach net zum laufen...Finde keine Fehler...:(

Beim Display handelt es sich um folgenden:
http://docs-europe.electrocomponents.com/webdocs/0...

Als µC benutze ich einen MEGA48 auf nem AVR-Board..
Für das Prog. habe ich eine Vorlage von Nollmeyer hier im Forum benutzt, 
dabei ein bisschen angepasst, wie Ports ect.
Wie zu sehen, benutze ich Port D.

Das Display gibt einfach keine Zeichen aus :( Außer, nach dem Start nur 
Rechtecke, also alle Pixel aktiv...

Am Kontrast habe ich schon herumgespielt, nix...
Die Display-Comments stimmen mit denen von meinem Display überein...So 
weit ich es korrekt kontrolliert habe. Naja, alle Display-Controller 
sind ja nahezu gleich...


::::::::::::::::::::::::::::::::::::::::::::::::::::Header

/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display 
----------------------------------------------------- */
/* 
*/
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT 
Modus betrieben.                         */
/* 
*/

#ifndef lcd_h
#define lcd_h

/* ---- Define BIT Variablen 
------------------------------------------------------------------------ 
---------  */
/* 
*/
#define HIGH 1                                                  /* 
digital High Pegel                          */
#define LOW  0                                                  /* 
digital Low Pegel                           */

/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar! 
-------------------------------------------------- */
/* 
*/
struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((_packed_));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O 
Defines vereinfachen                    */

/* ---- Define Display Signale 
------------------------------------------------------------------------ 
-------  */
/* 
*/
#define ENABLE SBIT (PORTD, 6)                                  // 
Display Enable
#define RS SBIT (PORTD, 4)                                      // 
Display RS BIT

/* ---- Define Display Kommandos 
------------------------------------------------------------------------ 
-----  */
/* 
*/
#define fs1 0x28 // 4 Bit Modus  2 Zeilen  5x7 Dots
#define fs2 0x2C // 4 Bit Modus  2 Zeilen  5x10 Dots
#define fs3 0x20 // 4 Bit Modus  1 Zeile  5x7 Dots
#define fs4 0x24 // 4 Bit Modus  1 Zeile  5x10 Dots

#define on_off_control_1    0x0C // Display An  Cursor Aus  Blink Aus
#define on_off_control_2    0x0E // Display An  Cursor An  Blink Aus
#define on_off_control_3    0x0F // Display An  Cursor An  Blink An
#define on_off_control_4    0x08 // Display Aus

#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
#define entrymode_2         0x07 // Cursor nach rechts / Shift
#define entrymode_3         0x04 // Cursor nach links / kein Shift
#define entrymode_4         0x05 // Cursor nach links / Shift

#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD 
Datenblatt; 80
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD 
Datenblatt; C0
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD 
Datenblatt
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD 
Datenblatt

#define clear_display       0x01 // Clear Display
#define cursor_home         0x02 // Cursor Home

/* ---- Define Prototypes 
------------------------------------------------------------------------ 
------------  */
/* 
*/
extern void lcd_command (uint8_t dsp_control_out);              // 
Funktion für Display Steuersignale
extern void lcd_char (uint8_t send_char);                       // 
Funktion Zeichen ausgeben
extern void lcd_init (void);                                    // 
Funktion LCD Initialisieren
extern void lcd_puts (const char *lcd_string);                  // 
Funktion Display String ausgeben

#endif

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display 
-------------------------------------- */
/* 
*/
/* (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT 
Modus betrieben.                         */
/* ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. 
WINAVR gcc 3.4.6                       */

/* ---- CPU CLOCK 
------------------------------------------------------------------------ 
-----  */
/* 
*/
#ifndef F_CPU
#define F_CPU 3686000UL // Frequenz in Hz
#endif

/* ---- Include Files 
------------------------------------------------------------------------ 
-  */
/* 
*/
#include <stdint.h>                                   /* ISO C99 Integer 
types        */
#include <avr/io.h>                                   /* ATTINY I/O's 
*/
#include <util/delay.h>                               /* delay Lib. 
*/
#include "lcd.h"                                      /* LCD Lib. 
*/

/* ---- MAIN 
------------------------------------------------------------------------ 
-----------  */

int main (void)  {
  DDRD = (1 << DDD6)                                   // Anschluß 
Display ENABLE
       | (1 << DDD0)                                   // Anschluß 
Display Datenbit DB4
       | (1 << DDD1)                                   // Anschluß 
Display Datenbit DB5
       | (1 << DDD2)                                   // Anschluß 
Display Datenbit DB6
       | (1 << DDD3)                                   // Anschluß 
Display Datenbit DB7
     | (1 << DDD4);                                 // Anschluß Display 
RS

  _delay_ms (15);                                      // wait 15 mSec. 
after Power ON
  lcd_init ();                                         // Display 
initialisieren
  lcd_puts ("WIN_AVR GCC");                            // Display Text

  for (;;);
}

/* ---- Display Ausgabe String 
------------------------------------------------------------------ */

void lcd_puts (const char *lcd_string)  {
  while (*lcd_string)  {
    lcd_char (*lcd_string++);                         // String auslesen 
und an LCD Ausgabe übergeben
  }
}

/* ---- Display Ausgabe Steuersignale 
----------------------------------------------------------- */

void lcd_command (uint8_t dsp_control_out)  {
  RS = LOW;                                           // Steuersignale 
an Display ausgeben (RS BIT=0)
  lcd_char (dsp_control_out);                         // Steuersignal 
ausgeben
  _delay_ms (4.1);                                    // Warteschleife 
4,1 mSec.
  RS = HIGH;                                          // RS BIT=1 => 
Daten
}

/* ---- Display Ausgabe Zeichen 
----------------------------------------------------------------- */

void lcd_char (uint8_t send_char)  {
  uint8_t n=2;                                         // Sende 2x 4 BIT 
(oberes Nibble zuerst)
  do  {
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low 
nibble nicht verändern
        ENABLE = HIGH;                                 // ENABLE = HIGH
        ENABLE = LOW;                                  // ENABLE = LOW, 
Steuersignal Datenübernahme
        send_char <<= 4;                               // unteres Nibble 
nach oben schieben
  }while (--n);
  _delay_us (42);                                      // Warteschleife 
42 uSec.
}

/* ---- Display initialisieren 
------------------------------------------------------------------ */

void lcd_init (void)  {
  uint8_t n = 3;                                       // Init. Sequenz, 
Referenz LCD Datenblatt
  do  {                                                // 3x 33H (0x03), 
init cycle 3x
        lcd_command (0x30);                            // DB4, DB5 = 1
  }while (--n);
  lcd_command (fs1);                              // 4 Bit Modus / 2 
Zeilen / 5x7 Dots
  lcd_command (on_off_control_1);                      // Display An / 
Cursor Aus / Blink Aus
  lcd_command (clear_display);                         // Clear Display
  lcd_command (entrymode_1);                           // Cursor nach 
rechts / kein Shift
}

Autor: Cosi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so ist besser:

::::::::::::::::::::::::::::::::::::::::::::::::::::Header
/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display
----------------------------------------------------- */
/*
*/
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT
Modus betrieben.                         */
/*
*/

#ifndef lcd_h
#define lcd_h

/* ---- Define BIT Variablen
---------------------------------------------------------------------------------
*/
/*
*/
#define HIGH 1                                                  /*
digital High Pegel                          */
#define LOW  0                                                  /*
digital Low Pegel                           */

/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar!
-------------------------------------------------- */
/*
*/
struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((__packed__));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O
Defines vereinfachen                    */

/* ---- Define Display Signale
-------------------------------------------------------------------------------
*/
/*
*/
#define ENABLE SBIT (PORTD, 6)                                  //
Display Enable
#define RS SBIT (PORTD, 4)                                      //
Display RS BIT

/* ---- Define Display Kommandos
-----------------------------------------------------------------------------
*/
/*
*/
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots

#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
#define on_off_control_4    0x08 // Display Aus

#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
#define entrymode_2         0x07 // Cursor nach rechts / Shift
#define entrymode_3         0x04 // Cursor nach links / kein Shift
#define entrymode_4         0x05 // Cursor nach links / Shift

#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD
Datenblatt; 80
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD
Datenblatt; C0
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD
Datenblatt
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD
Datenblatt

#define clear_display       0x01 // Clear Display
#define cursor_home         0x02 // Cursor Home

/* ---- Define Prototypes
------------------------------------------------------------------------------------
*/
/*
*/
extern void lcd_command (uint8_t dsp_control_out);              //
Funktion für Display Steuersignale
extern void lcd_char (uint8_t send_char);                       //
Funktion Zeichen ausgeben
extern void lcd_init (void);                                    //
Funktion LCD Initialisieren
extern void lcd_puts (const char *lcd_string);                  //
Funktion Display String ausgeben

#endif
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display
-------------------------------------- */
/*
*/
/* (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT
Modus betrieben.                         */
/* ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code.
WINAVR gcc 3.4.6                       */

/* ---- CPU CLOCK
-----------------------------------------------------------------------------
*/
/*
*/
#ifndef F_CPU
#define F_CPU 3686000UL // Frequenz in Hz
#endif

/* ---- Include Files
-------------------------------------------------------------------------
*/
/*
*/
#include <stdint.h>                                   /* ISO C99 Integer
types        */
#include <avr/io.h>                                   /* ATTINY I/O's
*/
#include <util/delay.h>                               /* delay Lib.
*/
#include "lcd.h"                                      /* LCD Lib.
*/

/* ---- MAIN
-----------------------------------------------------------------------------------
*/

int main (void)  {
  DDRD = (1 << DDD6)                                   // Anschluß
Display ENABLE
       | (1 << DDD0)                                   // Anschluß
Display Datenbit DB4
       | (1 << DDD1)                                   // Anschluß
Display Datenbit DB5
       | (1 << DDD2)                                   // Anschluß
Display Datenbit DB6
       | (1 << DDD3)                                   // Anschluß
Display Datenbit DB7
     | (1 << DDD4);                                 // Anschluß Display
RS

  _delay_ms (15);                                      // wait 15 mSec.
after Power ON
  lcd_init ();                                         // Display
initialisieren
  lcd_puts ("WIN_AVR GCC");                            // Display Text

  for (;;);
}

/* ---- Display Ausgabe String
------------------------------------------------------------------ */

void lcd_puts (const char *lcd_string)  {
  while (*lcd_string)  {
    lcd_char (*lcd_string++);                         // String auslesen
und an LCD Ausgabe übergeben
  }
}

/* ---- Display Ausgabe Steuersignale
----------------------------------------------------------- */

void lcd_command (uint8_t dsp_control_out)  {
  RS = LOW;                                           // Steuersignale
an Display ausgeben (RS BIT=0)
  lcd_char (dsp_control_out);                         // Steuersignal
ausgeben
  _delay_ms (4.1);                                    // Warteschleife
4,1 mSec.
  RS = HIGH;                                          // RS BIT=1 =>
Daten
}

/* ---- Display Ausgabe Zeichen
----------------------------------------------------------------- */

void lcd_char (uint8_t send_char)  {
  uint8_t n=2;                                         // Sende 2x 4 BIT
(oberes Nibble zuerst)
  do  {
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low
nibble nicht verändern
        ENABLE = HIGH;                                 // ENABLE = HIGH
        ENABLE = LOW;                                  // ENABLE = LOW,
Steuersignal Datenübernahme
        send_char <<= 4;                               // unteres Nibble
nach oben schieben
  }while (--n);
  _delay_us (42);                                      // Warteschleife
42 uSec.
}

/* ---- Display initialisieren
------------------------------------------------------------------ */

void lcd_init (void)  {
  uint8_t n = 3;                                       // Init. Sequenz,
Referenz LCD Datenblatt
  do  {                                                // 3x 33H (0x03),
init cycle 3x
        lcd_command (0x30);                            // DB4, DB5 = 1
  }while (--n);
  lcd_command (fs1);                              // 4 Bit Modus / 2
Zeilen / 5x7 Dots
  lcd_command (on_off_control_1);                      // Display An /
Cursor Aus / Blink Aus
  lcd_command (clear_display);                         // Clear Display
  lcd_command (entrymode_1);                           // Cursor nach
rechts / kein Shift
}

Autor: Fisch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Bin jetzt nur mal kurz drübergeflogen. Was mir aufgefallen ist:
Enable wird oben als sbit(PORTD, 6) definiert. Und weiter unten sagst du 
dann  ENABLE = HIGH. Das macht keinen Sinn. Ausserdem solltest du den 
Enable Impuls etwas länger auf HIGH lassen. Also noch ein kleines Delay 
einbauen.

Gruß Fisch

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Cosi

ich sehe bei deinem Code nicht, wie bei der Ausgabe eines Zeichens 
(Daten) per lcd_char die RS Leitung auf HIGH geht. Die Zeile
PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low

macht das unmöglich, da (PORTD & 0x0F) auch DDD4 löscht/auf LOW setzt! 
So gesehen schickst du nie Daten (Zeichen) ans LCD sondern immer ggf. 
illegale Kommandos.

Vergleiche mal, warum es beim Tutorialquellcode ZWEI Funktionen 
(lcd_data() und lcd_command()) gibt.

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beitrag "Wie mache ich eine Textausgabe 8Bit auf Display?"

Ist ausführlich erklärt und am Ende des Threads gibts nen Code zum
Testen und der funktioniert !!! Ich wiederhole mich...

Was hast du geändert ? Die Delays passen vermutlich nicht mehr, 
vergleiche mal den Quarztakt.

Der Rest ist ok. Der originale Code ist ebenso fehlerfrei !!!

Autor: Cosi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Joe, is er von dir :)
Du, habe nichts groß geändert, nur die Ports angepasst, weil ich den 
Port D nutze...Ebenso Taktfrequenz geändert...

Ich habe nun die Tipps von Fisch und Stefan mit berücksichtigt...Aber es 
geht noch immer nicht :(
/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display ----------------------------------------------------- */
/*                                                                                                             */
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT Modus betrieben.                         */
/*                                                                                                             */

#ifndef lcd_h
#define lcd_h

/* ---- Define BIT Variablen --------------------------------------------------------------------------------- */
/*                                                                                                             */
#define HIGH 1                                                  /* digital High Pegel                          */
#define LOW  0                                                  /* digital Low Pegel                           */

/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar! -------------------------------------------------- */
/*                                                                                                             */
struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((__packed__));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O Defines vereinfachen                    */

/* ---- Define Display Signale ------------------------------------------------------------------------------- */
/*                                                                                                             */
#define ENABLE 6                                  // Display Enable
#define RS 4                                      // Display RS BIT
//#define RS SBIT (PORTD, 4)

/* ---- Define Display Kommandos ----------------------------------------------------------------------------- */
/*                                                                                                             */
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots

#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
#define on_off_control_4    0x08 // Display Aus

#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
#define entrymode_2         0x07 // Cursor nach rechts / Shift
#define entrymode_3         0x04 // Cursor nach links / kein Shift
#define entrymode_4         0x05 // Cursor nach links / Shift

#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD Datenblatt; 80
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD Datenblatt; C0
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD Datenblatt
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD Datenblatt

#define clear_display       0x01 // Clear Display
#define cursor_home         0x02 // Cursor Home

/* ---- Define Prototypes ------------------------------------------------------------------------------------ */
/*                                                                                                             */
extern void lcd_command (uint8_t dsp_control_out);              // Funktion für Display Steuersignale
extern void lcd_char (uint8_t send_char);                       // Funktion Zeichen ausgeben
extern void lcd_init (void);                                    // Funktion LCD Initialisieren
extern void lcd_puts (const char *lcd_string);                  // Funktion Display String ausgeben

#endif



// ---- LCD Driver Routine for 2x16 / 4x20 char. Display
// (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT Modus betrieben.
// ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. WINAVR gcc 3.4.6

/* ---- CPU CLOCK ----------------------------------------------------------------------------- */

#ifndef F_CPU
#define F_CPU 3686000UL // Frequenz in Hz
#endif

/* ---- Include Files ------------------------------------------------------------------------- */

#include <stdint.h>                                   /* ISO C99 Integer types        */
#include <avr/io.h>                                   /* ATTINY I/O's                 */
#include <util/delay.h>                               /* delay Lib.                   */
#include "lcd.h"                                      /* LCD Lib.                     */

/* ---- MAIN ----------------------------------------------------------------------------------- */

int main (void)  {
  DDRD = (1 << DDD6)                                   // Anschluß Display ENABLE 
       | (1 << DDD0)                                   // Anschluß Display Datenbit DB4 
       | (1 << DDD1)                                   // Anschluß Display Datenbit DB5
       | (1 << DDD2)                                   // Anschluß Display Datenbit DB6
       | (1 << DDD3)                                   // Anschluß Display Datenbit DB7
     | (1 << DDD4);                                 // Anschluß Display RS
 
   _delay_ms (15);                                      // wait 15 mSec. after Power ON
  lcd_init ();                                         // Display initialisieren
  lcd_puts ("Hallo");                            // Display Text

  for (;;);
}

/* ---- Display Ausgabe String ------------------------------------------------------------------ */

void lcd_puts (const char *lcd_string)  {
  while (*lcd_string)  {
    lcd_char (*lcd_string++);                         // String auslesen und an LCD Ausgabe übergeben
  }
}

/* ---- Display Ausgabe Steuersignale ----------------------------------------------------------- */

void lcd_command (uint8_t dsp_control_out)  {    
  PORTD |= (1<<RS);                                  // Steuersignale an Display ausgeben (RS BIT=0)
  lcd_char (dsp_control_out);                         // Steuersignal ausgeben
  _delay_ms (4.1);                                    // Warteschleife 4,1 mSec.
  PORTD &= ~(1<<RS);                                          // RS BIT=1 => Daten
}

/* ---- Display Ausgabe Zeichen ----------------------------------------------------------------- */

void lcd_char (uint8_t send_char)
{
  uint8_t n=2;                               
  do  {                        // Sende 2x 4 BIT (oberes Nibble zuerst)
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);// Port low nibble nicht verändern
        PORTD|= (1<< ENABLE);                                 // ENABLE = HIGH
    _delay_ms(0.5);    // Impulszeit von E=High,in Doku: min 220ns
        PORTD &= ~(1<< ENABLE);                                  // ENABLE = LOW, Steuersignal Datenübernahme
        send_char <<= 4;                               // unteres Nibble nach oben schieben
  }while (--n);
  _delay_us (42);                                      // Warteschleife 42 uSec.
}

/* ---- Display initialisieren ------------------------------------------------------------------ */

void lcd_init (void)  {
  uint8_t n = 3;                                       // Init. Sequenz, Referenz LCD Datenblatt
  do  {                                                // 3x 33H (0x03), init cycle 3x
        lcd_command (0x33);                            // DB4, DB5 = 1
  }while (--n);
  lcd_command (fs1);                              // 4 Bit Modus / 2 Zeilen / 5x7 Dots
  lcd_command (on_off_control_1);                      // Display An / Cursor Aus / Blink Aus
  lcd_command (clear_display);                         // Clear Display
  lcd_command (entrymode_1);                           // Cursor nach rechts / kein Shift
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, das
PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);

macht nicht das Gewünschte. Futschgemacht ist futsch und später 
dazugefrickelt ist falsch.
PORTD = (PORTD & (0x0F | (1<<RS))) | (send_char & 0xF0);

ist besser. Aber jetzt beim Drüberschauen sehe ich, das das doch sowieso 
Murks ist.

Von PORTD sollen die Bits D0-D3 für die 4 Datenleitungen vom LCD benutzt 
werden, D4 für RS und D6 für ENABLE. Genau das macht diese Zeile NICHT:
PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);

Die löscht die D7-D4 und lässt D3-D0 so wie sie sind. Dazu wird das 
obere Nibble von sendchar geodert... Murks, irgendwann ist D3 bis D0 
komplett 1.

So soll es gehen (in Einzelanweisungen)
PORTD  = (PORTD & 0xF0);        // D3-D0 freimachen
PORTD |= (send_char & 0xF0)>>4; // oberes Nibble von send_char dazu.

bzw. in einer Zeile
PORTD  = (PORTD & 0xF0) | (send_char & 0xF0)>>4;

Autor: Cosi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan,
ok, stimmt, danke dir...

Aber es geht noch immer net heul
Habe schon andere ganz einfache Programme laufen lassen, nie eine 
Reaktion.

Hab die Pinbelegung bereits zig-Mal überprüft, die muss stimmen...
Vielleicht stimmt mit dem LCD was net, hmmm :(

Autor: Cosi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
habe mit den Code nochmal ganz genau angeschaut und debuggt. Keine 
Fehler gefunden...

Jedoch eine Frage:
In der Display-Doku (Seite 5) steht was von CG bzw. DD RAM Adresse 
setzen...Muss ich da auch was initialisieren?

Nach dem Senden der Zeichen (im Beispiel unten: "Aa") ist da das 
zurücksetzen vom RS-Bit notwenig?

Der aktuelle Code:
// ---- LCD Driver Routine for 2x16 / 4x20 char. Display                                                                                                             
// (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT Modus betrieben                       

#ifndef lcd_h
#define lcd_h

#define HIGH 1
#define LOW  0

#define ENABLE 6                                  // Display Enable
#define RS 4                                      // Display RS BIT
//#define RS SBIT (PORTD, 4)

/* ---- Define Display Kommandos ----------------------------------------------------------------------------- */
/*                                                                                                             */
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots

#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
#define on_off_control_4    0x08 // Display Aus

#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
#define entrymode_2         0x07 // Cursor nach rechts / Shift
#define entrymode_3         0x04 // Cursor nach links / kein Shift
#define entrymode_4         0x05 // Cursor nach links / Shift

#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD Datenblatt; 80
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD Datenblatt; C0
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD Datenblatt
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD Datenblatt

#define clear_display       0x01 // Clear Display
#define cursor_home         0x02 // Cursor Home

/* ---- Define Prototypes ------------------------------------------------------------------------------------ */
/*                                                                                                             */
extern void lcd_command (uint8_t dsp_control_out);              // Funktion für Display Steuersignale
extern void lcd_char (uint8_t send_char);                       // Funktion Zeichen ausgeben
extern void lcd_init (void);                                    // Funktion LCD Initialisieren
extern void lcd_puts (const char *lcd_string);                  // Funktion Display String ausgeben

#endif




// ---- LCD Driver Routine for 2x16 / 4x20 char. Display
// (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT Modus betrieben.
// ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. WINAVR gcc 3.4.6

#ifndef F_CPU
#define F_CPU 3686000UL // Frequenz in Hz
#endif

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"

int main (void)
{
  DDRD = (1 << DDD6)                                   // Anschluß Display ENABLE 
       | (1 << DDD0)                                   // Anschluß Display Datenbit DB4 
       | (1 << DDD1)                                   // Anschluß Display Datenbit DB5
       | (1 << DDD2)                                   // Anschluß Display Datenbit DB6
       | (1 << DDD3)                                   // Anschluß Display Datenbit DB7
     | (1 << DDD4);                                 // Anschluß Display RS
 
   _delay_ms (15);                                      // wait 15 mSec. after Power ON
  lcd_init ();                                         // Display initialisieren
  lcd_puts ("Aa");                            // Display Text

  for (;;);
}

/* ---- Display Ausgabe String ------------------------------------------------------------------ */

void lcd_puts (const char *lcd_string)
{
  while (*lcd_string)
  {
    lcd_char (*lcd_string++);                         // String auslesen und an LCD Ausgabe übergeben
  }
}

/* ---- Display Ausgabe Steuersignale ----------------------------------------------------------- */

void lcd_command (uint8_t dsp_control_out)
{    
  PORTD &= ~(1<<RS);                                  // Steuersignale an Display ausgeben (RS BIT=0)
  lcd_char (dsp_control_out);                         // Steuersignal ausgeben
  _delay_ms (4.1);                                    // Warteschleife 4,1 mSec.
  PORTD |= (1<<RS);                                  // RS BIT=1 => Daten
}

/* ---- Display Ausgabe Zeichen ----------------------------------------------------------------- */

void lcd_char (uint8_t send_char)
{
  uint8_t n=2;                               
  do  {                        // Sende 2x 4 BIT (oberes Nibble zuerst)
        PORTD  = (PORTD & 0xF0);        // D3-D0 freimachen
    PORTD |= (send_char & 0xF0)>>4; // oberes Nibble von send_char dazu.// Port low nibble nicht verändern
        PORTD|= (1<< ENABLE);                                 // ENABLE = HIGH
    _delay_ms(0.5);    // Impulszeit von E=High,in Doku: min 220ns
        PORTD &= ~(1<< ENABLE);                                  // ENABLE = LOW, Steuersignal Datenübernahme
        send_char <<= 4;                               // unteres Nibble nach oben schieben
  }while (--n);
  _delay_us (42);                                      // Warteschleife 42 uSec.
}

/* ---- Display initialisieren ------------------------------------------------------------------ */

void lcd_init (void)
{
  uint8_t n = 3;                                       // Init. Sequenz, Referenz LCD Datenblatt
  do  {                                                // 3x 33H (0x03), init cycle 3x
        lcd_command (0x30);                            // DB4, DB5 = 1
  }while (--n);
  lcd_command (fs1);                              // 4 Bit Modus / 2 Zeilen / 5x7 Dots
  lcd_command (on_off_control_1);                      // Display An / Cursor Aus / Blink Aus
  lcd_command (clear_display);                         // Clear Display
  lcd_command (entrymode_1);                           // Cursor nach rechts / kein Shift
  lcd_command (cursor_home);
}

Grüße, Cosi

Autor: Cosi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
In der LCD-Doku steht etwas zu den Zeiten, zu denen die E und RS-Bits 
gesetzt werden sollen...Habe ich bereits ohne Erfolg ausprobiert.

Im Tutorial wurde aber einfach zuerst RS-Bit, danach das E-Bit 
gesetzt...Die Daten liegen dabei schon an.
Das habe ich momentan so implementiert...

Vielleicht könnt ihr es kurz bei euch laufen lassen?! Ich komm echt 
nicht dahinter an was es liegen könnte...

Hab den Code auf das wesentliche abgespeckt.

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.