Ausgabe am LCD-Display (HD44780 kompatibel)

LCD-Modul 162B von Displaytech

Das alphanumerische LCD-Modul 162B von Displaytech verfügt über zwei Zeilen mit jeweils 16 Zeichen und verwendet den Controller KS0070B, der kompatibel zum Industriestandard HD44780 ist. Die Ansteuerung erfolgt parallel mit einem wahlweise 4 Bit oder 8 Bit breiten Datenbus.

Displaytech LCD-Modul 162B

 

Displaytech 162B - Pinbelegung

Pinbelegung LCD-Modul 162B

 

Anschlussplan des LCD-Moduls

Anschlussplan LCD-Modul 162B

 

Routine zur Display Ansteuerung

Hier eine C-Routine, welche ein LCD-Display (Displaytech 162B) im 2-Zeilen-4-Bit-Modus ansteuert.

/****************************************************************
* LCD Ausgabe für Hitachi HD44780 kompatible LCD Controller
*
* Mikroontroller: AT90PWM316
* Clock: 8MHz intern
* 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 R = 1kOhm) = LCD A
****************************************************************/


#define F_CPU 8000000

#include <avr/io.h>
#include <util/delay.h> 

#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
#define LCD_SETDDRAM 0x80 // Set Display RAM Address


/***** 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 0x0E // 0x0E = LCD ON, Cursor ON
#define LCD_OFF 0x08 // Display OFF

/***** HILFSDEFINITIONEN *****/

#define BEFEHL 0
#define DATEN 1
#define sbi(sfr, bit) (sfr |= (1<<bit))
#define cbi(sfr, bit) (sfr &= ~(1<<bit))


/****** Sendet ein Byte an den LCD Controller ******/
void lcd_send(unsigned char type, unsigned char c)
{
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(c, 7))
sbi(LCDPORT, LCD_PIN_D7);
else cbi(LCDPORT, LCD_PIN_D7);

if (bit_is_set(c, 6))
sbi(LCDPORT, LCD_PIN_D6);
else cbi(LCDPORT, LCD_PIN_D6);

if (bit_is_set(c, 5))
sbi(LCDPORT, LCD_PIN_D5);
else cbi(LCDPORT, LCD_PIN_D5);

if (bit_is_set(c, 4))
sbi(LCDPORT, LCD_PIN_D4);
else cbi(LCDPORT, LCD_PIN_D4);

/* Flanke zur Übernahme der Daten senden ... ******/
sbi(LCDPORT, LCD_PIN_E);
_delay_ms(1);
cbi(LCDPORT, LCD_PIN_E);


/* (2) LOW NIBBLE wird gesendet ******/
if (bit_is_set(c, 3))
sbi(LCDPORT, LCD_PIN_D7);
else cbi(LCDPORT, LCD_PIN_D7);

if (bit_is_set(c, 2))
sbi(LCDPORT, LCD_PIN_D6);
else cbi(LCDPORT, LCD_PIN_D6);

if (bit_is_set(c, 1))
sbi(LCDPORT, LCD_PIN_D5);
else cbi(LCDPORT, LCD_PIN_D5);

if (bit_is_set(c, 0))
sbi(LCDPORT, LCD_PIN_D4);
else cbi(LCDPORT, LCD_PIN_D4);

/* Flanke zur Übernahme der Daten senden ... ******/
sbi(LCDPORT, LCD_PIN_E);
_delay_ms(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)
{
unsigned char i;
for (i=0;i<255;i++)
{
if (t[i]==0) // String-Ende? Dann raus hier ...
return;
else
lcd_send(DATEN, t[i]);
}
}

/****** Initialisierung des LCD Controllers *****/
void lcd_init()
{
/* Port auf Ausgang schalten */
LCDPORT = 0x00;
LCDDDR = 0xFF;

_delay_ms(40); // Warten bis LCD bereit ...

/* 4-bit Modus konfigurieren ------Function-Set 1*/
sbi(LCDPORT, LCD_PIN_D5);
cbi(LCDPORT, LCD_PIN_D4);

_delay_ms(40);
/* 4-bit Modus konfigurieren ------Function-Set 2*/
sbi(LCDPORT, LCD_PIN_D5);
cbi(LCDPORT, LCD_PIN_D4);

_delay_ms(5);
/* 4-bit Modus konfigurieren ------Function-Set 3*/
sbi(LCDPORT, LCD_PIN_D5);
cbi(LCDPORT, LCD_PIN_D4);

/* 4-Bit Modus starten ... */
sbi(PORTD, LCD_PIN_E);
cbi(PORTD, LCD_PIN_E);
_delay_ms(5);

/* 2 Zeilen, 4-Bit Modus */
lcd_send(BEFEHL, 0x28);
//lcd_send(BEFEHL, 0x14);

lcd_send(BEFEHL, LCD_OFF);
lcd_send(BEFEHL, LCD_CLEAR);

lcd_send(BEFEHL, 0x06);
lcd_send(BEFEHL, LCD_ON);
}


/****** Hilfsfunktion: Warte i Sekunden ******/
void sekunde(char i)
{
unsigned char k;
for (;i>0;i--)
{
for (k=0;k<10;k++)
_delay_ms(50);
}
}

/***** HAUPTPROGRAMM *****/
int main(void)
{
_delay_ms(50);
lcd_init();
lcd_write("Starting LCD..."); 

while (1)
{
sekunde(5);
lcd_send(BEFEHL, LCD_CLEAR);
lcd_write("LCD-Test Zeile1");

sekunde(5);
lcd_send(BEFEHL, LCD_CLEAR);
lcd_send(BEFEHL, LCD_SETDDRAM +0x40); //Cursor auf 1.Position Zeile 2
lcd_write("LCD-Test Zeile2");
}
}

 

Praxisbeispiel Temperatursensor mit LCD-Anzeige

Dieses Beispiel misst mittels Temperatursensor MCP9700 und ADC-Wandlung die Temperatur.
Die Temperatur wird als int-Wert in der Variablen "ergebnis" gespeichert und durch die Funktion itoa in einen String für die LCD-Anzeige umgewandelt.

Die itoa-Funktion ist ein Bestandteil von WinAVR und erfordert das Einbinden von #include <stdlib.h>

Mehr zur itoa-Funktion finden Sie hier>>

 

C-Code für das abgeänderte Hauptprogramm:

/*****    HAUPTPROGRAMM    *****/
int main(void)
{

int x,ergebnis;
_delay_ms(50);
lcd_init();
lcd_write("Starting LCD...");


//**** Init ADC ****
ADCSRA |= 1<<ADEN; // ADC aktivieren
ADCSRA |= (1<<ADPS1)|(1<<ADPS2); // Vorteiler auf 64
ADMUX |= (1<<REFS0)|(1<<REFS1); // Einstellung Uref = 2,56V
ADMUX |= (1<<MUX2)|(1<<MUX0); // ADC5 (PIN PB2) als ADC-Kanal definieren
ADMUX |= (0<<ADLAR); // Ausgabe = linksbündig
DIDR0 |= 1<<ADC5D; // Digital Input Kanal ADC5 disabled

// nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
// also einen Wert ein und verwirft diesen, um den ADC "warmlaufen zu lassen"

ADCSRA |= (1<<ADSC); // Start ADC-Wandlung
while (ADCSRA & (1<<ADSC)); // auf Abschluss der Konvertierung warten
x = ADC; // ADCW muss einmal gelesen werden, sonst wird das
// Ergebnis der nächsten Wandlung nicht übernommen

char Buffer[20];

while (1)
{
ADCSRA |= (1<<ADSC); // Start ADC-Wandlung
while (ADCSRA & (1<<ADSC)); // auf Abschluss der Konvertierung warten
ergebnis = (ADC-200)/4; // Anpassung an die Temperaturkennlinie
// (y=kx+d) + etwaiger Korrekturfaktor

itoa(ergebnis,Buffer,10); // Aufruf der itoa-Funktion
// Die itoa-Funktion wandelt einen int-Wert in einen String um
// Unter WinAVR ist diese Funktion durch einbinden von #include <stdlib.h> verfügbar

sekunde(5);
lcd_send(BEFEHL, LCD_CLEAR);
lcd_write("LCD-Thermometer");

sekunde(5);
lcd_send(BEFEHL, LCD_CLEAR);
lcd_send(BEFEHL, LCD_SETDDRAM +0x40); //1.Position Zeile 2
lcd_write("Es hat ");
lcd_write(Buffer);
lcd_write(" C");
}
}