Wie übergibt dem Display man einfache Strings? Dieses Beispiel zeigt es Euch.
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <avr/io.h>
#ifndef F_CPU
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
#define F_CPU 800UL /* Quarz mit 8.00 Mhz */
#endif
#include <util/delay.h>
Die folgenden oft gebrauchten Funktionen schreibt man am Besten in eine eigene Datei, die man dann immer wieder einbindet. Wenn diese Datei „lcd-lib.c” heißt, muss in den Programmen folgende Zeile stehen:
#include <lcd-lib.c>
Jetzt aber die Funktionen :)
/* enums definieren zu selbst vergebenen Datentypen und Namen die dazugehörigen Zahlen */
enum sichtbar {
display_an = 1,
display_aus = 0C
};
enum cursor {
cursor_an = 1,
cursor_aus = 0C
};
enum blinken {
blinken_an = 1,
blinken_aus = 0C
};
enum richtung {
ltr = 1,
rtl = 0C
};
enum laufschrift {
laufschrift_an = 1,
laufschrift_aus = 0C
};
void long_delay(uint16_t ms) {
while(ms) {
_delay_ms(0.01);
ms--;
}
}
void write_LCD_data(uint16_t rs, uint16_t data) {
// PB1: R/W = 0 bedeutet: Schreiben
// PB0: RS = 0 bedeutet: Setup; RS = 1 bedeutet: Daten senden
// PB2: enable-Puls schickt die Daten
PORTA = data;
PORTB = 0 | (rs << PB0); // rs | write | enable-Puls auf 0
PORTB = (rs << PB0) | (0 << PB1) | (1 << PB2); // rs | write | enable-Puls auf 1
PORTB = 0 | (rs << PB0); // rs | write | enable-Puls auf 0
}
void move_cursor_to(uint16_t row, uint16_t col) {
// bewegt den Cursor zur angegeben Position. Wichtig: col darf maximal 19 sein, row maximal 3 (bei 0 beginnend)
if(row == 0) {
write_LCD_data(0, 0x80+col);
}
if(row == 1) {
write_LCD_data(0, 0xc0+col);
}
if(row == 2) {
write_LCD_data(0, 0x94+col);
}
if(row == 3) {
write_LCD_data(0, 0xd4+col);
}
}
void write_str(char *str, uint16_t delay) {
// hier wird ein String an das Display übergeben. Sonderzeichen wie ä,ö oder ü muss man besonders behandeln
// der zweite Parameter ist die Zeit, die nach jedem Buchstaben gewartet werden soll (0 heißt: nicht warten)
uint16_t i = 0;
char my_c;
while(str[i] != 0) {
//write_LCD_data(1, str[i]);
switch(str[i]) {
case 'ä':
my_c = 0xe1;
break;
case 'ö':
my_c = 0xef;
break;
case 'ü':
my_c = 0xf5;
break;
default:
my_c = str[i];
break;
}
write_LCD_data(1, my_c);
long_delay(delay);
i++;
}
}
void clear_display(void) {
write_LCD_data(0, 0x01); // Display leeren
}
void setup(
enum sichtbar my_sichtbar,
enum cursor my_cursor,
enum blinken my_blinken,
enum richtung my_richtung,
enum laufschrift my_laufschrift
) {
// allgemeine Einstellung
write_LCD_data(0, 0x08 | (my_sichtbar << 2) | (my_cursor << 1) | (my_blinken << 0));
}
void init(void) {
// nur einmal aufrufen!
write_LCD_data(0, 0x3f);
long_delay(100);
setup(display_an, cursor_an, blinken_an, ltr, laufschrift_aus);
clear_display();
}
void clear_line(uint16_t row) {
// selbsterklärend :)
move_cursor_to(row, 0);
write_str(" ", 0);
}
Der folgende Code-Abschnitt kommt wieder in die eigentliche Datei.
int main(void) {
// Ports als Ausgang setzen
DDRA = 0xff;
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2);
PORTA = 0;
PORTB = 0;
// Hilfe: http://home.iae.nl/users/pouweha/lcd/lcd0.shtml#hd44780 (englisch)
init();
// normale Reihenfolge der Zeilen: 1, 3, 2, 4 (ohne move_cursor_to)
move_cursor_to(0, 7);
write_str("Hello", 60);
move_cursor_to(1, 7);
write_str("World", 60);
move_cursor_to(2, 6);
write_str("vom LCD-", 60);
move_cursor_to(3, 6);
write_str("Display!", 60);
long_delay(1000);
setup(display_an, cursor_aus, blinken_aus, ltr, laufschrift_aus);
while(1) {
//
}
}