Skip to content

Instantly share code, notes, and snippets.

@avr-programmierung
Created May 16, 2019 12:43
Show Gist options
  • Save avr-programmierung/d8eb245292b1c7f76a9e94d11aec632f to your computer and use it in GitHub Desktop.
Save avr-programmierung/d8eb245292b1c7f76a9e94d11aec632f to your computer and use it in GitHub Desktop.
ATmega88 @ 8MHz LCD Ausgabe für Hitachi HD44780 kompatible LCD Controller
/****************************************************************
* 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
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment