Mikrocontroller und Digitale Elektronik
›
Thread
Problem mit Display
A
Andre
Gast
30.05.2010 22:06
#1729669
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;
}
//----------------------------------------------------------------------
-----
Ist dir aufgefallen, dass die Software die ganze Zeit an PortC
hantiert??
A
Andre
Gast
30.05.2010 22:46
#1729723
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;
}
//----------------------------------------------------------------------
-----
A
Andre
Gast
30.05.2010 22:48
#1729729
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
F
Flo
Gast
30.05.2010 23:25
#1729767
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;
A
Andre
Gast
30.05.2010 23:42
#1729781
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
F
Flo
Gast
30.05.2010 23:53
#1729788
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 :-)
A
Andre
Gast
31.05.2010 00:04
#1729799
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
F
Flo
Gast
31.05.2010 00:17
#1729808
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.
A
Andre
Gast
31.05.2010 00:39
#1729814
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);
A
Andre
Gast
31.05.2010 00:49
#1729818
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 ?!
A
Andre
Gast
31.05.2010 01:22
#1729828
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 :-)
PD
Peter D.
(peda)
31.05.2010 01:29
#1729830
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren