Hallo nochmals Danke!
Das Display LCD 202A von Reichelt zeigt zwar jetzt was an,abr nicht das
was es soll.
/* Das LCD ist folgendermaßen angeschlossen:
* PA4 = RS
* PA5 = Enable
* PA0-PA3 = A4-A7
* R/W ist n.c.
*
*
*/
#include <avr/io.h>
#include <util/delay.h>
#include "lcd_tools.h"
#define delay(us) _delay_loop_2 (((F_CPU/4000)*us)/1000) // wartet
µs
/*
wartet Millisekunden
Zeit in Millisekunden
*/
void delay_ms(uint16_t ms)
{
for(uint16_t t=0; t<=ms; t++)
_delay_ms(10); //1
}
/**
Enable Leitung togglen
*/
void lcd_flash_e ()
{
PORTA = PORTA | ( 1<<DDA5 ) ; // Enable = HIGH
delay(200);//100 // kurz warten, damit Flanke entsteht
PORTA = PORTA & ~( 1<<DDA5 ) ; // Enable = LOW
delay(200); //100 // Warten, bis der durch Enable angelegte
Befehl hoffentlich verarbeitet wurde
}
/**
Kommando oder Zeichen an Display senden:
rs=0 => Kommando, rs=1 => Zeichen
*/
void lcd_write (uint16_t data, uint16_t rs)
{
uint16_t dataBits ;
if (rs) // write data (RS=1, RW=0)
dataBits=0x10; // RS liegt an Pin 4 = B 0001 0000 = H 10
else // write instruction (RS=0, RW=0)
dataBits=0;
PORTA = dataBits | (data>>4); // output high nibble first, zzgl.
Zustand für RS-Leitung
lcd_flash_e ();
PORTA = dataBits | (data&0x0F); // output low nibble, zzgl.
RS-Leitung
lcd_flash_e ();
}
/**
Display loeschen
*/
void lcd_cls ()
{
lcd_write(0x00,0); // B 0000 0000 => Clear
delay(4000); // dauert eine Weile
lcd_write(0x01,0); // B 0000 0001 => Cursor Home
delay(4000); // dauert eine Weile, Wert ausprobiert
}
/**
Zeichenausgabe
*/
void lcd_writechar ( char zeichen)
{
lcd_write (zeichen, 1);
}
/**
gibt eine Zeichenkette auf dem LCD aus
*/
void lcd_writetext ( char *text)
{
uint16_t i = 0;
_delay_ms(10);//neu 18:50
while (text[i]!=0)
{
lcd_writechar(text[i]);
i++;
}
}
/**
Zeilenwechsel
*/
void lcd_gotoline (uint16_t zeile)
{
if (zeile == 1) lcd_write(0x80,0); // B 1000 0000 => DD-RAM
Adress Set 1. Zeile/1.Spalte
if (zeile == 2) lcd_write(0x80+0x40,0); // B 1010 0000 => DD-RAM
Adress Set 2. Zeile/1.Spalte
if (zeile == 3) lcd_write(0x80+0x13,0); // B 1010 0000 => DD-RAM
Adress Set 3. Zeile/1.Spalte
if (zeile == 4) lcd_write(0x80+0x53,0); // B 1010 0000 => DD-RAM
Adress Set 4. Zeile/1.Spalte
}
/**
Cursorpositionieren
Zeile, Spalte
*/
void lcd_gotopos (uint16_t zeile, uint16_t spalte)
{
if (zeile == 1) lcd_write(0x80+0x00+spalte-1,0); // DD-RAM Adress
1. Zeile + Spalte
if (zeile == 2) lcd_write(0x80+0x40+spalte-1,0); // DD-RAM Adress
2. Zeile + Spalte
if (zeile == 3) lcd_write(0x80+0x14+spalte-1,0); // DD-RAM Adress
3. Zeile + Spalte
if (zeile == 4) lcd_write(0x80+0x54+spalte-1,0); // DD-RAM Adress
4. Zeile + Spalte
}
/**
gibt eine int-Zahl auf dem Display aus.
space=0 => führende Nullen, 1 => führende Leerzeichen
*/
void lcd_writezahl (int32_t zahl, uint16_t pos, uint16_t spacer)
{
int32_t output;
char sign = '0';
pos--; // Korrektur des Parameters
if (spacer) sign=' ';
// negatives Vorzeichen oder Leerzeichen
if (zahl < 0)
{
lcd_writechar ('-');
zahl *= -1; // positive Zahl
}
output = zahl;
// Hunderttausender-Dezimalstelle oder Leerzeichen (Ausblenden
fuehrender Nullen)
if (zahl >= 100000) lcd_writechar (0x30 + output/100000); else if (pos
>= 5) lcd_writechar (sign);
output = output % 100000;
// Zehntausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender
Nullen)
if (zahl >= 10000) lcd_writechar (0x30 + output/10000); else if (pos
>= 4) lcd_writechar (sign);
output = output % 10000;
// Tausender-Dezimalstelle oder Leerzeichen
if (zahl >= 1000) lcd_writechar (0x30 + output/1000); else if (pos >=
3) lcd_writechar (sign);
output = output % 1000;
// Hunderter-Dezimalstelle oder Leerzeichen
if (zahl >= 100) lcd_writechar (0x30 + output/100); else if (pos >= 2)
lcd_writechar (sign);
output = output % 100;
// Zehner-Dezimalstelle oder Leerzeichen
if (zahl >= 10) lcd_writechar (0x30 + output/10); else if (pos >= 1)
lcd_writechar (sign);
// einer Dezimalstelle oder Leerzeichen
lcd_writechar (0x30 + output % 10);
}
/**
Zuerst den 8-Bit-Modus aktivieren, Ist wichtig, falls LCD schon im
4-Bit Modus war und dann
nach einem Programm-Reset vergeblich versucht würde, den 4-Bit Modus
erneut zu aktivieren.
Dann in 4-Bit Modus umschalten.
*/
void lcd_set4bit ()
{
PORTA = 0x03; // 8-Bit Modus aktivieren (B 0011 0000 = H 30,
High Nibble => B 0011 = H 03
lcd_flash_e (); // Datenübernahme
delay_ms(5); // sicherheitshalber warten da wir BUSY nicht
überprüfen können
// Das ganze 3x wiederholen:
PORTA = 0x03;
lcd_flash_e ();
delay(200);
PORTA = 0x03;
lcd_flash_e ();
delay(200);
lcd_write(0x02,0); // B 0000 0010 => in 4-Bit-Modus umschalten
delay(200);
}
/**
Portrichtung einstellen. Extern, damit man dies separat aufrufen kann,
wenn bspw. LCD schon initialisiert ist und
per Watchdog ein Reset ausgelöst wurde, man dann aber nicht das
Display neu initialisieren möchte, damit es schneller weiter geht
*/
void lcd_port_ini ()
{
DDRA = 0x3F; // setze Portrichtung (1 = Ausgang): 0011 1111
}
/**
Display initialisieren. Einmal als erstes aufrufen
*/
void lcd_ini ()
{
lcd_port_ini();
DDRA = 0x3F; // setze Portrichtung (1 = Ausgang): 0011 1111
delay_ms(40); // 40ms warten bis LCD wirklich bereit keine BUSY
Auswertung
lcd_set4bit(); // ab jetzt 4-Bit-Modus
lcd_write(0x28,0); // B 0010 1000 => Function Set: 4Bit (kein 8-Bit
Bus), zweizeiliges Display, 5x7 Dots/Zeichen RE-Bit aus
lcd_write(0x0F,0); // B 0000 1000 => Display On/Off: Display ein,
Cursor an, Blinken an
// lcd_write(0x0C,0); // B 0000 1000 => Display On/Off: Display ein,
Cursor aus, Blinken aus
lcd_write(0x06,0); // B 0000 0110 => Entry Mode Set: DD-RAM autom.
inkr., Cursor bewegen
lcd_cls(); // Display löschen
}
Vielen Dank!