Atmel AVR Mikrocontroller
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 162B - Pinbelegung
Anschlussplan des LCD-Moduls
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");
}
}