/**************************************************************** * LCD Ausgabe für Hitachi HD44780 kompatible LCD Controller * LCD-Initialisierung: 4-Bit Interface * Mikrocontroller: ATmega88 @ 8MHz * LCD-Display: Displaytech 162B (LCD-Controller KS0070B) * * Konfiguration: PORT D7 = LCD D7 * PORT D6 = LCD D6 * PORT D5 = LCD D5 * PORT D4 = LCD D4 * PORT D3 = LCD E * PORT D2 = LCD RS * GND = LCD Vss + LCD R/W + LCD K * +5V = LCD Vdd * Poti = LCD V0 * +5V (über 1kOhm) = LCD A ****************************************************************/ #include <avr/io.h> #include <util/delay.h> #include // Definitionen für die ITOA-Funktion einbinden /***** LCD Pinbelegung *****/ #define LCDPORT PORTD #define LCDDDR DDRD #define LCD_PIN_RS 2 #define LCD_PIN_E 3 #define LCD_PIN_D4 4 #define LCD_PIN_D5 5 #define LCD_PIN_D6 6 #define LCD_PIN_D7 7 /***** LCD STEUERBEFEHLE *****/ #define LCD_CLEAR 0x01 // Display löschen #define LCD_HOME 0x02 // Cursor an den Anfang zurück #define LCD_ON 0x0C // 0x0C = LCD ON, Cursor OFF #define LCD_ON_C 0x0E // 0x0E = LCD ON, Cursor ON #define LCD_OFF 0x08 // Display OFF #define LCD_SET_4Bit 0x28 // Set Function = 4-Bit, 2 Zeilen, 5x7 Matrix #define LCD_SET_2 0x06 // Entry Mode = Cursor increase, Display is not shifted #define LCD_SETDDRAM 0x80 // Set Display RAM Address /***** HILFSDEFINITIONEN *****/ #define BEFEHL 0 #define DATEN 1 #define sbi(port, bit) (port |= (1<<bit)) #define cbi(port, bit) (port &= ~(1<<bit)) /****** Sendet ein Byte an den LCD Controller ******/ void lcd_send(uint8_t type, uint8_t lcd_command) { if (type == BEFEHL) cbi(LCDPORT, LCD_PIN_RS); // RS=0: Befehl folgt ... else sbi(LCDPORT, LCD_PIN_RS); // RS=1: Daten folgen ... /* (1) HIGH NIBBLE wird gesendet */ if (bit_is_set(lcd_command, 7)) sbi(LCDPORT, LCD_PIN_D7); else cbi(LCDPORT, LCD_PIN_D7); if (bit_is_set(lcd_command, 6)) sbi(LCDPORT, LCD_PIN_D6); else cbi(LCDPORT, LCD_PIN_D6); if (bit_is_set(lcd_command, 5)) sbi(LCDPORT, LCD_PIN_D5); else cbi(LCDPORT, LCD_PIN_D5); if (bit_is_set(lcd_command, 4)) sbi(LCDPORT, LCD_PIN_D4); else cbi(LCDPORT, LCD_PIN_D4); /* Flanke zur Übernahme der Daten für das High-Nibble senden ... */ sbi(LCDPORT, LCD_PIN_E); _delay_us(1); cbi(LCDPORT, LCD_PIN_E); _delay_us(1); /* (2) LOW NIBBLE wird gesendet */ if (bit_is_set(lcd_command, 3)) sbi(LCDPORT, LCD_PIN_D7); else cbi(LCDPORT, LCD_PIN_D7); if (bit_is_set(lcd_command, 2)) sbi(LCDPORT, LCD_PIN_D6); else cbi(LCDPORT, LCD_PIN_D6); if (bit_is_set(lcd_command, 1)) sbi(LCDPORT, LCD_PIN_D5); else cbi(LCDPORT, LCD_PIN_D5); if (bit_is_set(lcd_command, 0)) sbi(LCDPORT, LCD_PIN_D4); else cbi(LCDPORT, LCD_PIN_D4); /* Flanke zur Übernahme der Daten für das Low-Nibble senden ... */ sbi(LCDPORT, LCD_PIN_E); _delay_us(1); cbi(LCDPORT, LCD_PIN_E); /* (3) Auf den LCD Controller warten ...*/ _delay_ms(5); } /****** Stellt eine Zeichenkette am LCD dar ******/ void lcd_write(char *t) // *t = pointer auf übergebenes Zeichen { uint8_t i; for (i=0; i<255; i++) { if (t[i]==0) // String-Ende (bei Wert = 0)? Dann raus hier ... return; else lcd_send(DATEN, t[i]); } } /****** Enable Impuls zur Übernahme der LCD-Daten ******/ void toggle_enable(void) { sbi(LCDPORT, LCD_PIN_E); _delay_us(1); cbi(LCDPORT, LCD_PIN_E); } /****** Initialisierung des LCD Controllers *****/ void lcd_init() { _delay_ms(60); // LCD-Power-On delay (min. 40ms) /* LCD Soft-Reset 1 – Kommando 0011xxxx */ sbi(LCDPORT, LCD_PIN_D5); // D5 = 1 sbi(LCDPORT, LCD_PIN_D4); // D4 = 1 toggle_enable(); // Kommando übernehmen _delay_ms(40); // Auf die Ausführung des LCD warten /* LCD Soft-Reset 2 – Kommando 0011xxxx */ toggle_enable(); // Kommando übernehmen (D5=1, D4=1) _delay_ms(1); // Auf die Ausführung des LCD warten /* LCD Soft-Reset 3 – Kommando 0011xxxx */ toggle_enable(); // Kommando übernehmen (D5=1, D4=1) _delay_ms(5); // Auf die Ausführung des LCD warten // Ab hier ist sicher der 8-Bit Mode eingestellt! // Jetzt folgt die Umstellung auf den 4-Bit Modus! /* 4-Bit Modus einschalten */ sbi(LCDPORT, LCD_PIN_D5); // LCD D5 = 1 cbi(LCDPORT, LCD_PIN_D4); // LCD D4 = 0 toggle_enable(); // Kommando übernehmen _delay_ms(5); // Ab hier im 4-Bit Modus (High-Nibble / Low-Nibble senden) // LCD auf 2 Zeilen, 4-Bit Modus, 5x7 Matrix einstellen lcd_send(BEFEHL, LCD_SET_4Bit); // Register SET FUNCTION = 0010 1000 lcd_send(BEFEHL, LCD_OFF); // Set LCD OFF lcd_send(BEFEHL, LCD_CLEAR); // Clear LCD lcd_send(BEFEHL, LCD_SET_2); // Set ENTRY MODE = 0000 0110 lcd_send(BEFEHL, LCD_ON); // Set LCD ON } /****** Hilfsfunktion: Warte i Sekunden ******/ void sekunde(uint8_t i) { uint8_t k; for (;i>0;i--) // Solange i>0 dekrementiere i um 1 { for (k=0;k<10;k++) // 10 Durchläufe mit je 50ms _delay_ms(50); } } /***** HAUPTPROGRAMM *****/ int main(void) { LCDDDR = 0xFF; // Port auf Ausgang schalten LCDPORT = 0x00; lcd_init(); // LCD initialisieren lcd_write("Starting LCD..."); char Buffer[20]; // Datentyp char für Zeichen uint8_t dezimalwert = 22; while (1) { // Aufruf der itoa-Funktion zur ASCII-Darstellung einer Dezimalzahl (Basis = 10) itoa(dezimalwert,Buffer,10); sekunde(5); lcd_send(BEFEHL, LCD_CLEAR); // LCD clear lcd_write("HALLO LCD!"); // Der Cursor befindet sich an 1.Position Zeile 1 sekunde(5); lcd_send(BEFEHL, LCD_CLEAR); // LCD clear lcd_send(BEFEHL, LCD_SETDDRAM +0x40); // Cursor auf die 1.Position Zeile 2 lcd_write("Wert = "); lcd_write(Buffer); // Schreibe den Inhalt des itoa-Buffers sekunde(5); lcd_send(BEFEHL, LCD_CLEAR); // LCD clear lcd_send(BEFEHL, LCD_SETDDRAM +0x42); // Cursor auf die 3.Position Zeile 2 lcd_write("Wert = "); lcd_write(Buffer); // Schreibe den Inhalt des itoa-Buffers } }