SKETCH‎ > ‎LCD-16x2‎ > ‎

Controller HD44780

NEU

http://sites.prenninger.com/arduino-uno-r3/sketch/lcd-16x2/controller-hd44780

http://www.linksammlung.info/

http://www.schaltungen.at/

                                                                                             Wels, am 2014-10-01

BITTE nützen Sie doch rechts OBEN das Suchfeld  [                                                              ] [ Diese Site durchsuchen]

DIN A3 oder DIN A4 quer ausdrucken
**********************************************************************************
DIN A4  ausdrucken
*********************************************************

Die immer vorkommenden ARDUINO Begriffe (Begrifflichkeiten ?) habe ich in einer EXCEL-Tabelle zusammengefaßt.

706_c_ARDUINO-x_ARDUINO UNO Rev.3 - Begrifflichkeiten (Grundlagen Wissen)_1a.xls




LCD Display 2x16 Modul 1602A  HD44780
http://funduino.de






AVR-GCC-Tutorial / LCD-Ansteuerung

Wechseln zu: Navigation, Suche

Das LCD und sein Controller

Die meisten Text-LCDs verwenden den Controller HD44780 oder einen kompatiblen (z. B. KS0070) und haben 14 oder 16 pins.

Hier ist die häufigste Anschluss-Belegung angegeben.

Achtung
Es gibt Displays mit abweichender Anschluss-Belegung,
z.B. TC1602E (Pollin 120420).
Falscher Anschluss kann zur Zerstörung führen!
Daher immer das zugehörige Datenblatt zu Rate ziehen.
Einzelheiten unter Artikel zum Controller HD44780.
Pin # Bezeichnung Funktion
1 Vss GND    (nur beim TC1602E Vdd=Vcc)
2 Vdd/Vcc 5V       (nur beim TC1602E Vss=GND)
3 Vee Kontrastspannung (0V bis 5V)
4 RS Register Select (Befehle/Daten)
5 RW Read/Write
6 E Enable
7 DB0 Datenbits 0−7
8 DB1
9 DB2
10 DB3
11 DB4
12 DB5
13 DB6
14 DB7
15 A LED-Beleuchtung, Anode
16 K LED-Beleuchtung, Kathode
Achtung
Unbedingt von der richtigen Seite zu zählen anfangen! Meistens ist neben Pin 1 eine kleine 1 auf der LCD-Platine. Ansonsten im Datenblatt nachschauen! Oft ist Pin 1 auch durch ein rechteckiges statt rundes Pad gekennzeichnet.
Bei LCDs mit 16-poligem Anschluss sind die beiden letzten Pins für die Hintergrundbeleuchtung reserviert. Hier unbedingt das Datenblatt zu Rate ziehen, die beiden Anschlüsse sind je nach Hersteller oft anders beschaltet. Falls kein Datenblatt vorliegt, kann man mit einem Durchgangsprüfer feststellen, welcher Anschluss mit Masse (GND) verbunden ist.

Vss wird ganz einfach an GND angeschlossen und Vcc an 5V.

Vee kann man testweise auch an GND legen.

Wenn das LCD dann zu dunkel sein sollte muss man ein 10k-Potentiometer zwischen GND und 5V schalten, mit dem Schleifer an Vee:

LCD Vee.gif

Es gibt zwei verschiedene Möglichkeiten zur Ansteuerung eines solchen Displays: den 8-bit- und den 4-bit-Modus.

  • Für den 8-bit-Modus werden (wie der Name schon sagt) alle acht Datenleitungen zur Ansteuerung verwendet, somit kann durch einen Zugriff immer ein ganzes Byte übertragen werden.
  • Der 4-bit-Modus verwendet nur die oberen vier Datenleitungen (DB4-DB7). Um ein Byte zu übertragen braucht man somit zwei Zugriffe, wobei zuerst das höherwertige "Nibble" (= 4 Bits), also Bit 4 bis Bit 7 übertragen wird und dann das niederwertige, also Bit 0 bis Bit 3. Die unteren Datenleitungen des LCDs, die beim Lesezyklus Ausgänge sind, lässt man offen (siehe Datasheets, z. B. vom KS0070).

Der 4-bit-Modus hat den Vorteil, dass man 4 IO-Pins weniger benötigt als beim 8-bit-Modus, weshalb ich mich hier für eine Ansteuerung mit 4bit entschieden habe.

Neben den vier Datenleitungen (DB4, DB5, DB6 und DB7) werden noch die Anschlüsse RS, RW und E (ist in manchen Unterlagen auch EN für Enable abgekürzt) benötigt.

  • Über RS wird ausgewählt, ob man einen Befehl oder ein Datenbyte an das LCD schicken möchte. Ist RS Low, dann wird das ankommende Byte als Befehl interpretiert, ist RS high, dann wird das Byte auf dem LCD angezeigt.
  • RW legt fest, ob geschrieben oder gelesen werden soll. High bedeutet lesen, low bedeutet schreiben. Wenn man RW auf lesen einstellt und RS auf Befehl, dann kann man das Busy-Flag an DB7 lesen, das anzeigt, ob das LCD den vorhergehenden Befehl fertig verarbeitetet hat (diese Methode u.a. in der LCD-Library von Peter Fleury verwendet). Ist RS auf Daten eingestellt, dann kann man z. B. den Inhalt des Displays lesen - was jedoch nur in den wenigsten Fällen Sinn macht. Deshalb kann man RW dauerhaft auf low lassen (= an GND anschließen), so dass man noch ein IO-Pin am Controller einspart. Der Nachteil ist, dass man dann das Busy-Flag nicht lesen kann, weswegen man nach jedem Befehl vorsichtshalber ein paar Mikrosekunden warten sollte, um dem LCD Zeit zum Ausführen des Befehls zu geben. Dummerweise schwankt die Ausführungszeit von Display zu Display und ist auch von der Betriebsspannung abhängig. Für professionellere Sachen also lieber den IO-Pin opfern und Busy abfragen.
  • Der E Anschluss schließlich signalisiert dem LCD, dass die übrigen Datenleitungen jetzt korrekte Pegel angenommen haben und es die gewünschten Daten von den Datenleitungen bzw. Kommandos von den Datenleitungen übernehmen kann.

Anschluss an den Controller

Jetzt da wir wissen, welche Anschlüsse das LCDs benötigt, können wir das LCD mit dem Mikrocontroller verbinden:

ACHTUNG: Es gibt Displays mit abweichender Anschluss-Belegung, falscher Anschluss kann zur Zerstörung führen! Daher immer das zugehörige Datenblatt zu Rate ziehen.

Einzelheiten unter Artikel zum Controller HD44780

Pin #-LCD Bezeichnung-LCD Pin-µC
1 Vss GND
2 Vcc 5V
3 Vee GND oder Poti (siehe oben)
4 RS PD4 am AVR
5 RW GND
6 E PD5 am AVR
7 DB0 offen (unbenutzt)
8 DB1
9 DB2
10 DB3
11 DB4 PD0 am AVR
12 DB5 PD1 am AVR
13 DB6 PD2 am AVR
14 DB7 PD3 am AVR

Wenn man die Steuerleitungen EN und RS auf Pins an einem anderen Port legen möchte, kann man so wie in diesem Forumsbeitrag oder wie im Artikel Erweiterte LCD-Ansteuerung vorgehen.

Ok, alles ist verbunden, wenn man jetzt den Strom einschaltet sollten ein oder zwei schwarze Balken auf dem Display angezeigt werden. Erscheint trotz korrektem Anschluss nichts auf dem Display, so kann das auch am Kontrast des LCDs liegen. Die Balken werden dann zwar theoretisch angezeigt, sind aber nicht sichtbar, weil die Kontrastspannung zu hoch ist. Abhilfe schafft es hier, wenn man die Spannung am Schleifer des Potis nachmisst und in Richtung 0V verstellt. Zwischen 1V und 0V treten die Balken dann meist hervor. Doch wie bekommt man jetzt die Befehle und Daten in das Display?

Programmierung

Die LCD Routinen

Der folgende Satz von Ansteuerroutinen für ein Text-LCD ist in der Datei lcd-routines.c zusammengefasst. Diese Datei muss man beim Einrichten zusätzlich zum eigenen Hauptprogramm in sein Projekt aufnehmen. Dies geschieht beim AVR Studio unter Source Files im Fenster AVR GCC oder bei WinAVR im Makefile (z. B. durch SRC += lcd-routines.c).

Wichtig ist außerdem, dass die Optimierung bei der Compilierung eingeschaltet ist, sonst stimmen die Zeiten der Funktionen _delay_us() und _delay_ms() nicht und der Code wird wesentlich länger (Siehe Dokumentation der libc im WinAVR).

Als weitere Datei ist die Includedatei lcd-routines.h notwendig, die im Hauptprogramm und in lcd-routines.c eingebunden wird. Die Anpassung der Pinbelegung etc. macht man in dieser Datei.

Datei lcd-routines.h

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
 
#ifndef LCD_ROUTINES_H
#define LCD_ROUTINES_H


usw.   #define LCD_GC_CHAR6 6 #define LCD_GC_CHAR7 7   // Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM) #define LCD_SET_DDADR 0x80   #endif

Datei lcd-routines.c:

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/HD44780
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
 
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
 
////////////////////////////////////////////////////////////////////////////////
// Erzeugt einen Enable-Puls

usw.
//////////////////////////////////////////////////////////////////////////////// // Schreibt ein Zeichen in den Character Generator RAM   void lcd_generatechar( uint8_t code, const uint8_t *data ) { // Startposition des Zeichens einstellen lcd_command( LCD_SET_CGADR | (code<<3) );   // Bitmuster übertragen for ( uint8_t i=0; i<8; i++ ) { lcd_data( data[i] ); } }



LCD Beispiel 1

Ein Hauptprogramm, welches die LCD Funktionen benutzt, sieht zb. so aus:

 
/* Anpassungen im makefile:
   ATMega8 => MCU=atmega8 im makefile einstellen
   lcd-routines.c in SRC = ... Zeile anhängen
*/ 
#include <avr/io.h> #include "lcd-routines.h"   int main(void) { /* Initialisierung des LCD Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken */ verschwunden sein lcd_init();   lcd_data( 'T' ); // Text in einzelnen Zeichen ausgeben lcd_data( 'e' ); lcd_data( 's' ); lcd_data( 't' );   lcd_setcursor( 0, 2 ); // Die Ausgabemarke in die 2te Zeile setzen   lcd_string("Hello World!"); // erneut Text ausgeben, aber diesmal komfortabler als String   while(1) { }   return 0; }


LCD Beispiel 2

Ein Hauptprogramm, welches eine Variable ausgibt, sieht zb. so aus.

Mittels der itoa() Funktion (itoa = Integer To Ascii ) wird von einem Zahlenwert eine textuelle Repräsentierung ermittelt (sprich: ein String erzeugt)

und dieser String mit der bereits vorhandenen Funktion lcd_string ausgegeben. Das Einrichten des Projekts ist wie in Beispiel 1.

// 
// Anpassungen im makefile:
//    ATMega8 => MCU=atmega8 im makefile einstellen
//    lcd-routines.c in SRC = ... Zeile anhängen 
// 
#include <avr/io.h>
#include <stdlib.h>
#include "lcd-routines.h"
 
// Beispiel
int variable = 42;
 
int main(void)
{
  lcd_init();
 
  // Ausgabe des Zeichens dessen ASCII-Code gleich dem Variablenwert ist
  // (Im Beispiel entspricht der ASCII-Code 42 dem Zeichen *)
  // http://www.code-knacker.de/ascii.htm
  lcd_data( variable );
 
  lcd_setcursor( 0, 2 );
 
  // Ausgabe der Variable als Text in dezimaler Schreibweise
  {
     // ... umwandeln siehe FAQ Artikel bei http://www.mikrocontroller.net/articles/FAQ
     // WinAVR hat eine itoa()-Funktion, das erfordert obiges #include <stdlib.h>
     char Buffer[20]; // in diesem {} lokal
     itoa( variable, Buffer, 10 ); 
 
     // ... ausgeben  
     lcd_string( Buffer );
  }
 
  while(1)
  {
  }
 
  return 0;
}

Siehe auch

Weblinks




Quelle:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung




*********************************************************


AVR-GCC libraries

I have developed the following libraries which can be used with the AVR-GCC compiler:
Tested with AVR-GCC (WinAVR 20060125 or newer) using a AT90S8515-8PC at 4 Mhz and ATmega8 at 1Mhz and 4 Mhz.
All libraries are open  source under the GNU GPL license.

  • I2C Master Interface
    This library consists of a C include file i2cmaster.h and an assembler module i2cmaster.S.
    It can be used to communicate with I2C devices (serial eeprom, serial RTC etc) from any AVR device.
    i2cmaster.zip Online Manual HTML Help Manual

http://homepage.hispeed.ch/peterfleury/avr-software.html#libs




*********************************************************



Erweiterte LCD-Ansteuerung

Wechseln zu: Navigation, Suche

Einleitung

Die folgende Software beruht zum größten Teil auf dem Tutorial zur LCD-Ansteuerung. Eine Anpassung war jedoch nötig, weil in der Tutorial-Vorlage die vier LCD-Datenleitungen DB4 bis DB7 immer mit den unteren vier Portleitungen PIN0 bis PIN3 des Ausgabeports verbunden sein müssen. Die hier vorgestellte Lösung ermöglicht es, die als Datenleitung verwendeten Pins innerhalb des Ausgabeports freier zu konfigurieren. D.h.

  • Die vier Datenleitungen können als Bus beliebig an einem Port gelegt werden
  • Allerdings muss die Reihenfolge immer noch eingehalten werden, sprich, DB4-DB7 in aufsteigender Reihenfolge!
  • Die beiden anderen Steuersignale E und RS sind auf den übrigen vier Pins eines Ports frei wählbar
  • Das Signal RW muss am LCD fest auf GND gelegt sein, es werden nur Schreibzugriffe ausgeführt
  • Das Busy-Flag wird nicht genutzt
  • Wer die ultimativ freie Zuordnung von Pins über Portgrenzen hinweg haben will, muss die bekannte Bibliothek von Peter Fleury nutzen, siehe Links am Ende des Artikels

Ansonsten sind einige kosmetische Änderungen gemacht worden, die den Code etwas leichter lesbar machen sollen. So sind sämtliche Kommandos und Kommandooptionen als #defines ausgeführt. Gegenüber dem Original sind folgende Änderungen bzw. Erweiterungen gemacht worden:

  • konfigurierbare Datenleitungen, z.B. zum Anschluss von DB4-DB7 an PD4-PD7
  • Funktionsname lcd_setcursor() statt set_cursor() (einheitliche Namenskonvention)
  • einheitliche Verwendung von uint8_t
  • neue Funktion lcd_out() für eine 4bit-Operation
  • alle Kommandos und Kommandooptionen des LCD als #defines ausgeführt
  • neue Funktion lcd_generatechar() und lcd_generatechar_P() zum Generieren eines Zeichens im Character Generator RAM
  • ein Demoprogramm, in dem alle Funktionen der Bibliotek in ihrer Nutzung dargestellt sind

Alle Dateien sind als ZIP-Archiv hier verfügbar. Das Programm wurde komplett auf einem ATmega8515 getestet. Es ist auf ein 4x16 LCD ausgelegt. Wenn man das Programm auf seiner eigenen Hardware testen will, müssen folgende Dinge angepasst werden

  • in main.h das #define F_CPU für die Taktfrequenz
  • in lcd.h die Port- und Pinzuordnung mit LCD_PORT, LCD_DDR etc.

Der Quelltext ist ausgiebig kommentiert und sollte die Funktionen gut erklären.

Die erweiterten LCD-Routinen

Datei lcd.h

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
 
#ifndef LCD_ROUTINES_H
#define LCD_ROUTINES_H
 
#include <avr/pgmspace.h>
 
////////////////////////////////////////////////////////////////////////////////
// Pinbelegung für das LCD, an verwendete Pins anpassen
// alle Pins müssen in einem Port liegen
// die 4 Bit für die Daten müssen zusammenliegen, können aber an einer
// beliebigen Postion anfangen  
 
#ifndef LCD_PORTS
#define LCD_PORTS
 
#define LCD_PORT      PORTC
#define LCD_DDR       DDRC
 
// 4 Bit LCD Datenbus DB4-DB7, das unterste Bit DB4 kann auf den Portbits 0..4 liegen
 
//  LCD DB4-DB7 <-->  PORTC Bit PC0-PC3
#define LCD_DB        PC0
 
// LCD Steuersignale RS und EN
 
//  LCD RS      <-->  PORTC Bit PC4     (RS: 0=Data, 1=Command)
#define LCD_RS        PC4
 
//  LCD EN      <-->  PORTC Bit PC5     (EN: 1-Impuls für Daten)
#define LCD_EN        PC5
 
#endif // LCD_PORTS
 
////////////////////////////////////////////////////////////////////////////////
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
 
#ifndef LCD_TIMINGS
#define LCD_TIMINGS
 
#define LCD_BOOTUP_MS           15
#define LCD_ENABLE_US           1
#define LCD_WRITEDATA_US        46
#define LCD_COMMAND_US          42
 
#define LCD_SOFT_RESET_MS1      5
#define LCD_SOFT_RESET_MS2      1
#define LCD_SOFT_RESET_MS3      1
#define LCD_SET_4BITMODE_MS     5
 
#define LCD_CLEAR_DISPLAY_MS    2
#define LCD_CURSOR_HOME_MS      2
 
#endif // LCD_TIMINGS
 
////////////////////////////////////////////////////////////////////////////////
// Zeilendefinitionen des verwendeten LCD
// die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
// bei anderen Zeilenlängen müssen diese Einträge angepasst werden
 
#define LCD_DDADR_LINE1         0x00
#define LCD_DDADR_LINE2         0x40
#define LCD_DDADR_LINE3         0x10
#define LCD_DDADR_LINE4         0x50
 
////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void );
 
////////////////////////////////////////////////////////////////////////////////
// LCD löschen
void lcd_clear( void );
 
////////////////////////////////////////////////////////////////////////////////
// Cursor in die erste Zeile, erste Spalte (Position 0,0)
void lcd_home( void );
 
////////////////////////////////////////////////////////////////////////////////
// Cursor an eine beliebige Position 
void lcd_setcursor( uint8_t x, uint8_t y );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition 
void lcd_data( uint8_t data );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition 
// String liegt im RAM
void lcd_string( const char *data );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an einer bestimmten Cursorposition 
// String liegt im RAM
void lcd_string_xy( uint8_t x, uint8_t y, const char *data );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe einer Zahl an der aktuellen Cursorposition 
// Zahl liegt im RAM
void lcd_number( uint8_t number, uint8_t len, uint8_t fill );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe einer Zahl an einer bestimmten Cursorposition 
// Zahl liegt im RAM
void lcd_number_xy( uint8_t x, uint8_t y, uint8_t number, uint8_t len, uint8_t fill );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition
// String liegt im Flash 
void lcd_string_P( PGM_P data );
 
////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array mit den Zeilencodes des zu definierenden Zeichens
// zeigen, Daten liegen im RAM
void lcd_generatechar( uint8_t code, const uint8_t *data, uint8_t lines );
 
////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array mit den Zeilencodes des zu definierenden Zeichens
// zeigen, Daten liegen im FLASH
void lcd_generatechar_P( uint8_t code, PGM_P data, uint8_t lines );
 
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Kommandos an das LCD.
void lcd_command( uint8_t data );
 
////////////////////////////////////////////////////////////////////////////////
// LCD Befehle und Argumente.
// zur Verwendung in lcd_command
 
// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY       0x01
 
// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME         0x02
 
// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY           0x04
 
#define LCD_ENTRY_DECREASE      0x00
#define LCD_ENTRY_INCREASE      0x02
#define LCD_ENTRY_NOSHIFT       0x00
#define LCD_ENTRY_SHIFT         0x01
 
// Set Display ---------------- 0b00001xxx
#define LCD_SET_DISPLAY         0x08
 
#define LCD_DISPLAY_OFF         0x00
#define LCD_DISPLAY_ON          0x04
#define LCD_CURSOR_OFF          0x00
#define LCD_CURSOR_ON           0x02
#define LCD_BLINKING_OFF        0x00
#define LCD_BLINKING_ON         0x01
 
// Set Shift ------------------ 0b0001xxxx
#define LCD_SET_SHIFT           0x10
 
#define LCD_CURSOR_MOVE         0x00
#define LCD_DISPLAY_SHIFT       0x08
#define LCD_SHIFT_LEFT          0x00
#define LCD_SHIFT_RIGHT         0x01
 
// Set Function --------------- 0b001xxxxx
#define LCD_SET_FUNCTION        0x20
 
#define LCD_FUNCTION_4BIT       0x00
#define LCD_FUNCTION_8BIT       0x10
#define LCD_FUNCTION_1LINE      0x00
#define LCD_FUNCTION_2LINE      0x08
#define LCD_FUNCTION_5X7        0x00
#define LCD_FUNCTION_5X10       0x04
 
#define LCD_SOFT_RESET          0x30
 
// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
#define LCD_SET_CGADR           0x40
 
#define LCD_GC_CHAR0            0
#define LCD_GC_CHAR1            1
#define LCD_GC_CHAR2            2
#define LCD_GC_CHAR3            3
#define LCD_GC_CHAR4            4
#define LCD_GC_CHAR5            5
#define LCD_GC_CHAR6            6
#define LCD_GC_CHAR7            7
 
// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
#define LCD_SET_DDADR           0x80
 
 
#endif // LCD_ROUTINES_H

Datei lcd.c

// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// http://www.mikrocontroller.net/articles/HD44780
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
//
// Die Pinbelegung ist über defines in lcd.h einstellbar
 
#include <avr/io.h>
#include "main.h"
#include "lcd.h"
#include <util/delay.h>
 
/////////////////////////////////////////////////////////////////////////////////
// Erzeugt einen Enable-Puls
 
static void lcd_enable( void ) {
    LCD_PORT |= (1<<LCD_EN);            // Enable auf 1 setzen
    _delay_us( LCD_ENABLE_US );         // kurze Pause
    LCD_PORT &= ~(1<<LCD_EN);           // Enable auf 0 setzen
}
 
////////////////////////////////////////////////////////////////////////////////
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( uint8_t data ) {
    data &= 0xF0;                       // obere 4 Bit maskieren
    LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
    LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
    lcd_enable();
}
 
////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void ) {
    // verwendete Pins auf Ausgang schalten
    uint8_t pins = (0x0F << LCD_DB) |   // 4 Datenleitungen
                   (1<<LCD_RS) |        // R/S Leitung
                   (1<<LCD_EN);         // Enable Leitung
    LCD_DDR |= pins;
 
    // initial alle Ausgänge auf Null
    LCD_PORT &= ~pins;
 
    // warten auf die Bereitschaft des LCD
    _delay_ms( LCD_BOOTUP_MS );
 
    // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
    lcd_out( LCD_SOFT_RESET );
    _delay_ms( LCD_SOFT_RESET_MS1 );
 
    lcd_enable();
    _delay_ms( LCD_SOFT_RESET_MS2 );
 
    lcd_enable();
    _delay_ms( LCD_SOFT_RESET_MS3 );
 
    // 4-bit Modus aktivieren 
    lcd_out( LCD_SET_FUNCTION |
             LCD_FUNCTION_4BIT );
    _delay_ms( LCD_SET_4BITMODE_MS );
 
    // 4-bit Modus / 2 Zeilen / 5x7
    lcd_command( LCD_SET_FUNCTION |
                 LCD_FUNCTION_4BIT |
                 LCD_FUNCTION_2LINE |
                 LCD_FUNCTION_5X7 );
 
    // Display ein / Cursor aus / Blinken aus
    lcd_command(LCD_SET_DISPLAY |
                LCD_DISPLAY_ON |
                LCD_CURSOR_OFF |
                LCD_BLINKING_OFF); 
 
    // Cursor inkrement / kein Scrollen
    lcd_command( LCD_SET_ENTRY |
                 LCD_ENTRY_INCREASE |
                 LCD_ENTRY_NOSHIFT );
 
    lcd_clear();
}
 
////////////////////////////////////////////////////////////////////////////////
// Sendet ein Datenbyte an das LCD
void lcd_data( uint8_t data ) {
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
 
    lcd_out( data );            // zuerst die oberen, 
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden
 
    _delay_us( LCD_WRITEDATA_US );
}
 
////////////////////////////////////////////////////////////////////////////////
// Sendet einen Befehl an das LCD
void lcd_command( uint8_t data ) {
    LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
 
    lcd_out( data );             // zuerst die oberen, 
    lcd_out( data<<4);           // dann die unteren 4 Bit senden
 
    _delay_us(LCD_COMMAND_US );
}
 
////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl zur Löschung des Displays
void lcd_clear( void ) {
    lcd_command( LCD_CLEAR_DISPLAY );
    _delay_ms( LCD_CLEAR_DISPLAY_MS );
}
 
////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl: Cursor Home
void lcd_home( void ) {
    lcd_command( LCD_CURSOR_HOME );
    _delay_ms( LCD_CURSOR_HOME_MS );
}
 
////////////////////////////////////////////////////////////////////////////////
// Setzt den Cursor in Zeile y (0..3) Spalte x (0..15)
 
void lcd_setcursor( uint8_t x, uint8_t y ) {
    uint8_t data;
 
    switch (y) {
        case 0:    // 1. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
            break;
        case 1:    // 2. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
            break;
        case 2:    // 3. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
            break;
        case 3:    // 4. Zeile
            data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
            break;
        default:    
            return; // für den Fall einer falschen Zeile
    }
 
    lcd_command( data );
}
 
////////////////////////////////////////////////////////////////////////////////
// Schreibt einen String auf das LCD
 
void lcd_string( const char *data ) {
    while( *data != '\0' )
        lcd_data( *data++ );
}
 
void lcd_string_xy( uint8_t x, uint8_t y, const char *data ) {
    lcd_setcursor( x, y );
    lcd_string( data );
}
 
////////////////////////////////////////////////////////////////////////////////
// Schreibt eine Zahl auf das LCD
 
void lcd_number( uint8_t number, uint8_t len, uint8_t fill ) {
    uint8_t digit1 = 0;
    uint8_t digit2 = 0;
    while (number >= 100) {
        digit1++;
        number -= 100;
    }
    while (number >= 10) {
        digit2++;
        number -= 10;
    }
    if (len > 2) lcd_data( (digit1 != 0) ? digit1+'0' : fill );
    if (len > 1) lcd_data( ((digit1 != 0) || (digit2 != 0)) ? digit2+'0' : fill );
    lcd_data( number+'0' );
}
 
void lcd_number_xy( uint8_t x, uint8_t y, uint8_t number, uint8_t len, uint8_t fill ) {
    lcd_setcursor( x, y );
    lcd_number( number, len, fill );
}
 
////////////////////////////////////////////////////////////////////////////////
// Schreibt einen String auf das LCD
// String liegt direkt im Flash Speicher
 
void lcd_string_P( PGM_P data ) {
    uint8_t tmp;
 
    tmp = pgm_read_byte( data );
    while( tmp != '\0' ) {        
        lcd_data( tmp );
        data++;
        tmp = pgm_read_byte( data );
    }
}
 
////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im RAM
 
void lcd_generatechar( uint8_t code, const uint8_t *data, uint8_t lines ) {
    uint8_t i;
 
    // Startposition des Zeichens einstellen
    lcd_command( LCD_SET_CGADR | (code<<3) );
    // Bitmuster übertragen
    for ( i=0; i<lines; i++ ) {
        lcd_data( *data++ );
    }
}
 
////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im Flash-Speicher
 
void lcd_generatechar_P( uint8_t code, PGM_P data, uint8_t lines ) {
    uint8_t i;
 
    // Startposition des Zeichens einstellen
    lcd_command( LCD_SET_CGADR | (code<<3) );
    // Bitmuster übertragen
    for ( i=0; i<lines; i++ ) {
        lcd_data( pgm_read_byte(data) );
        data++;
    }
}

Weblinks


http://www.mikrocontroller.net/articles/Erweiterte_LCD-Ansteuerung






DIN A4 ausdrucken

*********************************************************

Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:schaltungen@schaltungen.at
ENDE
Comments