Als Anhänger der Learning by doing Methode wollte ich bei meinen ersten
Berührungen mit LCD's versuchen lediglich die Ports des MyAvr Beispiels
zu tauschen.
Ursprünglich war
4-BitModus an PortD Bit 4-7
PortD Bit 2 = RS
PortD Bit 3 = E
dies wollte ich wechseln in
4-BitModus an PortB Bit 2-5
PortD Bit 0 = RS
PortD Bit 1 = E
Allerdings funktioniert nix .Vielleicht kann mir hier mal jemand auf die
Sprünge helfen.
Zum Beispiel bei Cursor auf Position 1,1 wäre ja 00000010 bei PORTD
gewesen .Allerdings war auf dem PIN 1 ja niemals irgendwas vom Display
angeschlossen .
Sicher für manche eine blöde Frage allerdings würde ich mich trotzdem um
etwas Hilfe freuen .
Lieben Gruß
//----------------------------------------------------------------------
-----
// Titel : myAVR Beispiel "LCD Ausgabe auf zwei Zeilen" für den
ATmega8/48/88/168
//----------------------------------------------------------------------
-----
// Funktion : gibt Zeichenketten auf dem myAVR LCD Modul, 2 Zeilen
// Schaltung : PORTC.2 = RS, PORTC.3 = E, PORTC.4-7 = D4-7
//----------------------------------------------------------------------
-----
// Prozessor :
// Takt : 3.6864 MHz
// Sprache : C
// Datum : 09.11.2007
// Version : 1.0
// Autor : S. Hänsel
// Programmer : ...
// Port : ...
//----------------------------------------------------------------------
#define F_CPU 3686400
#include <avr\io.h>
////////////////////////////////////////////////////////////////////////
//////
// LCD-Funktionen für myAVR-Board + myAVR-LCD
// 4-BitModus an PortD Bit 4-7
// PortD Bit 2 = RS, high=Daten, low=Kommando
// PortD Bit 3 = E, high-Impuls für gültige Daten
//----------------------------------------------------------------------
-----
// lcd_send(..) - sendet ein Byte an LCD im 4-Bit-Modus
// RS muss vorher richtig gesetzt sein
// PE: data=zu sendendes Byte
//----------------------------------------------------------------------
-----
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTC;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0b111100;
tmp|=rs;
PORTC=tmp;
// Schreibsignal
sbi(PORTC,1);
cbi(PORTC,1);
// Low-Teil senden
tmp=data;
tmp&=0b000011;
tmp*=16;
tmp|=rs;
PORTC=tmp;
// Schreibsignal
sbi(PORTC,1);
cbi(PORTC,1);
// verarbeiten lassen
waitMs(1);
}
//----------------------------------------------------------------------
-----
// lcd_cmd(..) - sendet ein Kommando an LCD
// PE: cmd=Kommando-Byte
//----------------------------------------------------------------------
-----
void lcd_cmd(char cmd)
{
cbi(PORTC,0); // RS löschen = Kommando
lcd_send(cmd); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet ein Zeichen (Daten) an LCD
// PE: text=Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char text)
{
sbi(PORTC,0); // RS setzen = Daten
lcd_send(text); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// Die Zeichenkette muss mit 0x00 abgeschlossen sein
// PE: pText=Zeiger auf Zeichenkette
//----------------------------------------------------------------------
-----
void lcd_write(const char* pText)
{
while(pText[0]!=0)
{
lcd_write(pText[0]);
pText++;
}
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// PE: pText=Zeiger auf Zeichenkette
// count=Anzahl der zu sendenden Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char* pText, int count)
{
while(count!=0)
{
lcd_write(pText[0]);
pText++;
count--;
}
}
//----------------------------------------------------------------------
-----
// lcd_home(..) - Cursor auf Position 1,1
//----------------------------------------------------------------------
-----
void lcd_home()
{
lcd_cmd(0x02);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_clear(..) - löscht die Anzeige im LCD
//----------------------------------------------------------------------
-----
void lcd_clear()
{
lcd_cmd(0x01);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_on(..) - schaltet das LCD an
//----------------------------------------------------------------------
-----
void lcd_on()
{
lcd_cmd(0x0E);
}
//----------------------------------------------------------------------
-----
// lcd_off(..) - schaltet das LCD aus
//----------------------------------------------------------------------
-----
void lcd_off()
{
lcd_cmd(0x08);
}
//----------------------------------------------------------------------
-----
// lcd_goto(..) - setzt die Cursorposition
// PE: row = Zeile 1..2
// col = Spalte 1..16
//----------------------------------------------------------------------
-----
void lcd_goto(int row, int col)
{
row--; // Null-basierend
row&=0x01; // sicherheitshalber
row*=0x40; // Zeile nach Bit 6 bringen
col--; // Null-basierend
col&=0x0f; // sicherheitshalber
char tmp=row|col;
tmp|=0x80; // Cursor setzen
lcd_cmd(tmp); // senden
}
//----------------------------------------------------------------------
-----
// lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//----------------------------------------------------------------------
-----
void lcd_init()
{
// Port D = Ausgang
DDRC=0b111111;
PORTC=0;
// warten bist LCD-Controller gebootet
waitMs(50);
// SOFT-RESET
PORTC = 0b110000; //0b00110000;
sbi(PORTC,1);
cbi(PORTC,1);
waitMs(5);
PORTC = 0b110000; //0b00110000;
sbi(PORTC,1);
cbi(PORTC,1);
waitMs(1);
PORTC = 0b110000; //0b00110000;
sbi(PORTC,1);
cbi(PORTC,1);
waitMs(5);
// 4-BitModus einschalten
PORTC=0b100000;
// Schreibsignal
sbi(PORTC,1);
cbi(PORTC,1);
waitMs(5);
// ab hier im 4-Bit-Modus
lcd_cmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
//lcd_off();
lcd_cmd(0x06); // Entry Mode
lcd_on();
lcd_clear();
}
//----------------------------------------------------------------------
-----
// Main-Funktion
//----------------------------------------------------------------------
-----
int main (void)
{
waitMs(200);
lcd_init();
lcd_goto(1,1);
lcd_write("Hallo");
lcd_goto(2,1);
lcd_write("myAVR!");
while (1) { } // Mainloop
return 0;
}
//----------------------------------------------------------------------
-----
Nein nein das ist ja das was ich schon geändert habe .
Hier ist das Original :
//----------------------------------------------------------------------
-----
// Titel : myAVR Beispiel "LCD Ausgabe auf zwei Zeilen" für den
ATmega8/48/88/168
//----------------------------------------------------------------------
-----
// Funktion : gibt Zeichenketten auf dem myAVR LCD Modul, 2 Zeilen
// Schaltung : PORTD.2 = RS, PORTD.3 = E, PORTD.4-7 = D4-7
//----------------------------------------------------------------------
-----
// Prozessor :
// Takt : 3.6864 MHz
// Sprache : C
// Datum : 09.11.2007
// Version : 1.0
// Autor : S. Hänsel
// Programmer : ...
// Port : ...
//----------------------------------------------------------------------
#define F_CPU 3686400
#include <avr\io.h>
////////////////////////////////////////////////////////////////////////
//////
// LCD-Funktionen für myAVR-Board + myAVR-LCD
// 4-BitModus an PortD Bit 4-7
// PortD Bit 2 = RS, high=Daten, low=Kommando
// PortD Bit 3 = E, high-Impuls für gültige Daten
//----------------------------------------------------------------------
-----
// lcd_send(..) - sendet ein Byte an LCD im 4-Bit-Modus
// RS muss vorher richtig gesetzt sein
// PE: data=zu sendendes Byte
//----------------------------------------------------------------------
-----
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTD;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0xf0;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// Low-Teil senden
tmp=data;
tmp&=0x0f;
tmp*=16;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// verarbeiten lassen
waitMs(1);
}
//----------------------------------------------------------------------
-----
// lcd_cmd(..) - sendet ein Kommando an LCD
// PE: cmd=Kommando-Byte
//----------------------------------------------------------------------
-----
void lcd_cmd(char cmd)
{
cbi(PORTD,2); // RS löschen = Kommando
lcd_send(cmd); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet ein Zeichen (Daten) an LCD
// PE: text=Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char text)
{
sbi(PORTD,2); // RS setzen = Daten
lcd_send(text); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// Die Zeichenkette muss mit 0x00 abgeschlossen sein
// PE: pText=Zeiger auf Zeichenkette
//----------------------------------------------------------------------
-----
void lcd_write(const char* pText)
{
while(pText[0]!=0)
{
lcd_write(pText[0]);
pText++;
}
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// PE: pText=Zeiger auf Zeichenkette
// count=Anzahl der zu sendenden Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char* pText, int count)
{
while(count!=0)
{
lcd_write(pText[0]);
pText++;
count--;
}
}
//----------------------------------------------------------------------
-----
// lcd_home(..) - Cursor auf Position 1,1
//----------------------------------------------------------------------
-----
void lcd_home()
{
lcd_cmd(0x02);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_clear(..) - löscht die Anzeige im LCD
//----------------------------------------------------------------------
-----
void lcd_clear()
{
lcd_cmd(0x01);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_on(..) - schaltet das LCD an
//----------------------------------------------------------------------
-----
void lcd_on()
{
lcd_cmd(0x0E);
}
//----------------------------------------------------------------------
-----
// lcd_off(..) - schaltet das LCD aus
//----------------------------------------------------------------------
-----
void lcd_off()
{
lcd_cmd(0x08);
}
//----------------------------------------------------------------------
-----
// lcd_goto(..) - setzt die Cursorposition
// PE: row = Zeile 1..2
// col = Spalte 1..16
//----------------------------------------------------------------------
-----
void lcd_goto(int row, int col)
{
row--; // Null-basierend
row&=0x01; // sicherheitshalber
row*=0x40; // Zeile nach Bit 6 bringen
col--; // Null-basierend
col&=0x0f; // sicherheitshalber
char tmp=row|col;
tmp|=0x80; // Cursor setzen
lcd_cmd(tmp); // senden
}
//----------------------------------------------------------------------
-----
// lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//----------------------------------------------------------------------
-----
void lcd_init()
{
// Port D = Ausgang
DDRD=0xff;
PORTD=0;
// warten bist LCD-Controller gebootet
waitMs(50);
// SOFT-RESET
PORTD = 0x30; //0b00110000;
sbi(PORTD,3);
cbi(PORTD,3);
waitMs(5);
PORTD = 0x30; //0b00110000;
sbi(PORTD,3);
cbi(PORTD,3);
waitMs(1);
PORTD = 0x30; //0b00110000;
sbi(PORTD,3);
cbi(PORTD,3);
waitMs(5);
// 4-BitModus einschalten
PORTD=0x20;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
waitMs(5);
// ab hier im 4-Bit-Modus
lcd_cmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
//lcd_off();
lcd_cmd(0x06); // Entry Mode
lcd_on();
lcd_clear();
}
//----------------------------------------------------------------------
-----
// Main-Funktion
//----------------------------------------------------------------------
-----
int main (void)
{
waitMs(200);
lcd_init();
lcd_goto(1,1);
lcd_write("Hallo");
lcd_goto(2,1);
lcd_write("myAVR!");
while (1) { } // Mainloop
return 0;
}
//----------------------------------------------------------------------
-----
dies wollte ich wechseln in 4-BitModus an PortC Bit 2-5 PortC Bit 0 = RS PortC Bit 1 = E sorry steht dort oben falsch
Allein in der lcd_send ist schon einiges falsch:
Andre schrieb:
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTC;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0b111100; //ähm 0xF0 (original) sind 0b11110000
tmp|=rs;
PORTC=tmp;
// Schreibsignal
sbi(PORTC,1);
cbi(PORTC,1);
// Low-Teil senden
tmp=data;
tmp&=0b000011; // hier sollte 0b00001111 stehen
tmp*=16;
tmp|=rs;
Ja ich habe hier irgendwie was grundlegendes nicht richtig verstanden . Wieso sind die lcd_cmd Befehle mit 8 bits belegt ?! Ich nutze an PortC 6 Pins wie beschrieben und auch früher waren bei PortD nur 6 Pins belegt . Zum Beispiel habe ich versucht das umzuschreiben // ab hier im 4-Bit-Modus lcd_cmd(0b00101000); // Funktions-Set: 2 Zeilen 5x7 Matrix, 4 Bit //lcd_off(); lcd_cmd(0b00000110); // Entry Mode lcd_on(); lcd_clear(); wie kann das zb sein das im entry mode früher Bit 1 mit high belegt war wenn dort nichts vom Display angeschlossen war ?! . Ich kapier's nicht heeelp
Das läuft so: Du hast ein Display, das 8 bit-Daten und -Befehle will. Jetzt denkt man sich 8 Pins nur für die Datenleitungen zum Display ist Verschwendung, also beschränkt man sich auf 4. Nun muss man allerdings 2 mal 4 Bit übertragen, um einen Befehl oder Datum (Einzahl von Daten?) mit 8 Bit senden zu können. Das geschieht über das Maskieren, die in deinem Programm nicht ganz stimmt. Andre schrieb: > 4-BitModus an PortC Bit 2-5 > PortC Bit 0 = RS > PortC Bit 1 = E Angenommen, dein Datenbyte ist data (8bit): tmp = data; tmp = tmp & 0b11110000; //alles, was in tmp mit 0 verundet & wird, ist platt (0) //--> obere 4 Bit damit dass an die richtigen Ausgänge kommt (PC5 - PC2), musst du tmp 2 mal nach rechts schieben: tmp = tmp >> 2; //geschoben um 2 Stellen dann mit RS und takten, dann kommt die untere Hälfte: tmp = data; tmp = tmp & 0b00001111; //diesmal sind die oberen 4 Bit platt, Rest bleibt damit die Anschlüsse passen, 2 mla nach links schieben: tmp = tmp << 2; //geschoben um 2 Stellen dann wieder RS und takten. Nun ist das ganze Datenbyte im Display :-)
Ok schonmal super vielen Dank für die Erklärung war mir wirklich nicht
ganz klar und mir deshalb ein Rätsel warum auf einmal wieder mit 8Bit
gearbeitet wird .
Wenn ich das allerdings mal versuche umzusetzen bleibt das Display
trotzdem schwarz ?!
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTB;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0b11110000;
tmp|=rs;
PORTB=tmp;
// Schreibsignal
sbi(PORTB,1);
cbi(PORTB,1);
// Low-Teil senden
tmp=data;
tmp&=0b00001111;
tmp*=16;
tmp|=rs;
PORTB=tmp;
// Schreibsignal
sbi(PORTB,1);
cbi(PORTB,1);
// verarbeiten lassen
waitMs(1);
}
//----------------------------------------------------------------------
-----
// lcd_cmd(..) - sendet ein Kommando an LCD
// PE: cmd=Kommando-Byte
//----------------------------------------------------------------------
-----
void lcd_cmd(char cmd)
{
cbi(PORTB,0); // RS löschen = Kommando
lcd_send(cmd); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet ein Zeichen (Daten) an LCD
// PE: text=Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char text)
{
sbi(PORTB,0); // RS setzen = Daten
lcd_send(text); // senden
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// Die Zeichenkette muss mit 0x00 abgeschlossen sein
// PE: pText=Zeiger auf Zeichenkette
//----------------------------------------------------------------------
-----
void lcd_write(const char* pText)
{
while(pText[0]!=0)
{
lcd_write(pText[0]);
pText++;
}
}
//----------------------------------------------------------------------
-----
// lcd_write(..) - sendet eine Zeichenkette an LCD
// PE: pText=Zeiger auf Zeichenkette
// count=Anzahl der zu sendenden Zeichen
//----------------------------------------------------------------------
-----
void lcd_write(char* pText, int count)
{
while(count!=0)
{
lcd_write(pText[0]);
pText++;
count--;
}
}
//----------------------------------------------------------------------
-----
// lcd_home(..) - Cursor auf Position 1,1
//----------------------------------------------------------------------
-----
void lcd_home()
{
lcd_cmd(0b00000010);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_clear(..) - löscht die Anzeige im LCD
//----------------------------------------------------------------------
-----
void lcd_clear()
{
lcd_cmd(0b00000001);
waitMs(2); // warten
}
//----------------------------------------------------------------------
-----
// lcd_on(..) - schaltet das LCD an
//----------------------------------------------------------------------
-----
void lcd_on()
{
lcd_cmd(0b00001110);
}
//----------------------------------------------------------------------
-----
// lcd_off(..) - schaltet das LCD aus
//----------------------------------------------------------------------
-----
void lcd_off()
{
lcd_cmd(0b00001000);
}
//----------------------------------------------------------------------
-----
// lcd_goto(..) - setzt die Cursorposition
// PE: row = Zeile 1..2
// col = Spalte 1..16
//----------------------------------------------------------------------
-----
void lcd_goto(int row, int col)
{
row--; // Null-basierend
row&=0b00000001; // sicherheitshalber
row*=0b01000000; // Zeile nach Bit 6 bringen
col--; // Null-basierend
col&=0b00001111; // sicherheitshalber
char tmp=row|col;
tmp|=0b10000000; // Cursor setzen
lcd_cmd(tmp); // senden
}
//----------------------------------------------------------------------
-----
// lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//----------------------------------------------------------------------
-----
void lcd_init()
{
// Port D = Ausgang
DDRB=0b111111;
PORTB=0;
// warten bist LCD-Controller gebootet
waitMs(50);
// SOFT-RESET
PORTB = 0b001100; //0b00110000;
sbi(PORTB,1);
cbi(PORTB,1);
waitMs(5);
PORTB = 0b001100; //0b00110000;
sbi(PORTB,1);
cbi(PORTB,1);
waitMs(1);
PORTB = 0b001100; //0b00110000;
sbi(PORTB,1);
cbi(PORTB,1);
waitMs(5);
// 4-BitModus einschalten
PORTB=0b001000;
// Schreibsignal
sbi(PORTB,1);
cbi(PORTB,1);
waitMs(5);
// ab hier im 4-Bit-Modus
lcd_cmd(0b00101000); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
lcd_off();
lcd_cmd(0b00000110); // Entry Mode
lcd_on();
lcd_clear();
}
//----------------------------------------------------------------------
-----
// Main-Funktion
//----------------------------------------------------------------------
-----
int main (void)
{
waitMs(200);
lcd_init();
lcd_goto(1,1);
lcd_write("Hallo");
lcd_goto(2,1);
lcd_write("myAVR!");
while (1) { } // Mainloop
return 0;
}
//----------------------------------------------------------------------
-----
Naja ich versuch mich nochmal irgendwie reinzudenken
Du musst die 4 Bit Daten, die du aus dem 8 Bit Datenbyte kriegst, ja auch an den Pins rausgeben, wo du das Display dran hast. Nach deinen Worten ist das LCD auf PC5 bis PC2, hier musst du deine 4-Bit-Werte passend hinschieben: (1 = interessante Stellen, 0 = unbedeutend) Deine High-4-Bit: 11110000 Dein PC (wie ein Tor): PC5-PC2 xx xx passt nicht ganz gell? Also High-4-Bit 2 mal nach rechts schieben: Deine High-4-Bit: 00111100 Dein PC (wie ein Tor): PC5-PC2 xx xx passt :-D Das selbe für Low-4-Bit, nur musst du da nach links schieben.
Okay das oben verstehe ich leider nur so halb .
Es sieht im Moment so bei mir aus :
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTB;
rs&=1; // habe ich auf die aktuelle Situation
angepasst sollte also stimmen
// High-Teil senden
char tmp=data;
tmp&=0b11110000;´ // hier bin ich mir unsicher ?!
tmp|=rs;
PORTB=tmp;
// Schreibsignal
sbi(PORTB,1);
cbi(PORTB,1);
// Low-Teil senden
tmp=data;
tmp&=0b00001111; // hier bin ich unsicher ?!
tmp*=16; // und zuletzt hier .Ich nehme an das ist die
Verschiebung ?! aber wiese war diese früher 16 ?!
tmp|=rs;
PORTB=tmp;
// Schreibsignal
sbi(PORTB,1);
cbi(PORTB,1);
// verarbeiten lassen
waitMs(1);
Ah ok deine Erklärung habe ich soweit verstanden .Funktioniert trotzdem noch nicht . Muss ich jetzt auch sämtliche andere Befehle angleichen die im 4 bit modus arbeiten ?! . Ja oder ?!
Perfekt funktioniert vielen Dank . Hab dieses //tmp*=16; einfach gekillt und siehe da es geht . Ich wüsste zwar immernoch gerne wofür das gut sein soll aber ok :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.