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.