C OLED mit HD44780 treibt mich in den Wahnsinn

Drehzahl-Löffel

Neues Mitglied
26. Sep. 2012
3
0
0
Sprachen
Hallo Community!

Das ist mein erster Beitrag bei euch.
Außerdem bin ich noch kompletter Anfänger in der µC-Welt.

Ich bräuchte eure Hilfe bei folgendem Projekt:
Möchte ein OLED Display 2x8 Zeichen von electronic-Assembly ansteuern. http://www.lcd-module.de/produkte/oled.html
µC ist ein Atmega8. Programmiert wird in C mit dem AVR Studio 6.

Ich bekomme die Initialisierung schon hin. Schreiben kann ich auch etwas. Alles Tutti ;)

Was nicht funktioniert ist, ich kann den Cursor nicht verschieben und dann an eine neue Position schreiben.
Cursor beliebig versetzen klappt. Aber danach schreibt das Display nichts mehr.

Habt ihr da eine Idee zu?

Wäre super!

Code habe ich im Anhang

PS: habe vergessen zu erwähnen, dass der Controller nur 44780 kompatibel ist.
Das macht die Sache natürlich nicht leichter
 

Anhänge

  • OLED test_v3.c
    5,3 KB · Aufrufe: 28
Fehler lokalisiert, brauche trotzdem Hilfe

Auch ein blindes Huhn.....usw

Ich habe den Fehler tatsächlich gefunden.

Es liegt an meiner Busy-Flag Abfrage.

Wenn ich diese Abfrage nach dem Senden von Befehlen nicht mache, funktioniert alles, wie gewünscht.
Nur ist das natürlich nicht die beste Lösung. Möchte das schon gerne mit drin haben.

Könnt ihr mir sagen, was an meiner Busy-Flag Abfrage falsch ist?
Laut datenblatt bekomme ich das Busy-Flag, wenn ich Leitungen RS=1 und R/W=0 setze.

Die Datenleitungen des Displays sind bei mir am Port D angeschlossen.
Die Steuersignale laufen über Port B.


Hier mal die entsprechenden Code-Schnippel:

Code:
//-----------------------------------
//----- Busy-Flag abfragen
//-----------------------------------
uint8_t pruefeBusyFlag(void)
{
    
uint8_t BusyFlag = 0x00;

    DDRD = 0x00;                                    // kompletter Port D als Eingang
    DDRB |= ( 1 << PB0 )|( 1 << PB1 );   // PB0, PB1 als Ausgang setzen
    PORTB &= ~(1<<PB0);                      //PBo auf NULL setzen Also RS=0
    PORTB |= (1<<PB1);                       //PB1 auf EINS setzen Also RW=1

    BusyFlag = PIND & (1<<PD7);
    BusyFlag = BusyFlag>>7;                //MSB 7mal nach rechts schieben also auf das LSB
    
    return BusyFlag;
}

Und hier die Stelle, an der ich nach dem senden eines Befehls warten möchte, bis das Busy-Flag wieder LOW ist:

Code:
//-----------------------------------
//----- Befehle senden
//-----------------------------------
void schreibeBefehl (uint8_t befehl)
{    
    
        DDRD = 0xFF;            // alle Ports von Register D als Ausgang setzen
                                // PD0...PD7 = DB0...DB7 des Displays
        DDRB = 0xFF;            //Ports von Register B als Ausgang nutzen
        PORTB &= ~(1<<PB0);        // RS = 0
        PORTB &= ~(1<<PB1);        // RW = 0
                                            
        PORTD = befehl;            // Befehl an Display ausgeben
        wartemikrosekunden(1);
        PORTB |= (1<<PB2);        // EN = 1
        wartemikrosekunden(1);    // Ausgang stabilisieren
        PORTB &= ~(1<<PB2);        // EN = 0
        
        
        // Abfrage vom Busy Flag funktioniert nicht !!!        
        while (pruefeBusyFlag())
            {
                  ;
            }
}
 
Hallo dino!
richtig, so sieht es schon besser aus! Danke.

habe es in der Zwischenzeit rausgefunden.
Ich hatte einen Denkfehler in der Busy-Abfrage.
Wenn man die daten vom Dispay lesen will, muss das ENABLE Signal vorher HIGH sein, dann von PIND lesen, danach ENABLE wieder auf LOW setzen.
Das ganze muss man außerdem 2mal machen, sonst klappt es bei mir zumindest nicht.

Hier mal der aktuelle, funktionierende Code:
Variablen
Code:
uint8_t BusyZustand = 0b00000000;
uint8_t BusyHIGH =0b10000000;
uint8_t BusyErgebnis = 0b10000000;
Busy-Abfrage
Code:
//-----------------------------------
//----- Busy zyklisch checken
//-----------------------------------
void BusyAbfrage(void)
{
	BusyZustand = 0b00000000;
	BusyHIGH =0b10000000;
	BusyErgebnis = 0b10000000;
	
	while(BusyErgebnis>0)
	{
		DDRD = 0x00;
		DDRB |= ( 1 << PB0 )|( 1 << PB1 );   // PB0, PB1 als Ausgang setzen
		PORTB &= ~(1<<PB0); 	//löschen (PBo auf NULL setzen)
		PORTB |= (1<<PB1);  	//PB1 auf EINS setzen
		//RS = 0
		//RW = 1
		wartemikrosekunden(5);
		
		PORTB |= (1<<PB2);		// EN = 1
		wartemikrosekunden(5);		// warte 5µs Ausgang stabilisieren
		BusyZustand=PIND;	//Busy-Flag abholen
		PORTB &= ~(1<<PB2);		// EN = 0
		
		PORTB |= (1<<PB2);		// EN = 1
		wartemikrosekunden(5);		// warte 5µs Ausgang stabilisieren
		BusyZustand=PIND;	//Busy-Flag abholen
		PORTB &= ~(1<<PB2);		// EN = 0
			
			
		BusyErgebnis= BusyZustand & BusyHIGH;
	}
}

So klappt es jetzt wunderbar!

Die 5µs versuche ich jetzt noch etwas zu optimieren. Das geht sicherlich noch schneller ;)
 
Hi,

habe glaub ich das selbe Display (EA W162-X3LW).
Ich finde die Helligkeit eher mäßig (ist auch per PWM runter geregelt). Und ich habe was in dem für EA typisch magerem Datenblatt von einem Grafikmodus gelesen, was natürlich nicht näher erwähnt worden ist.

Hatte sowas bereits erlebt mit einem 4x20 LCD von denen was ich via SPI betreiben wollte. Da wurde wenigstens noch auf das Datenblatt des eigentlich verwendetem Controllers verwiesen wo auch wirklich alles beschrieben worden ist. Diese beigefügten "Datenblätter" reichen ja grade mal für eine oberflächliche Inbetriebnahme... Bei diesem Display war leider kein solcher Hinweis, kA was da für ein Controller genau drin sitzt... Weiß das jemand?
 
Hab EA ne Mail geschickt und prompt das Datenblatt bekommen.
Es ist der WS0010, leicht via Google zu finden :)

Edit: Aber über den Grafik Mode ist da auch nichts zu finden 0.o

Edit die 2.: Doch steht drin, habs nur übersehen...
"Use DDRAM address instruction to set X-axis address of Graphic mode and CGRAM address instruction
to set Y-axis of Graphic mode."
 
Noch mal eine kleine Randnotiz zu dem Display bevor sich noch einer halb tot sucht:

Punkt 1: Es hat 4 Zeichensätze statt 3. Ärgerlich dass in jedem Zeichensatz mindestens 1 deutsches Umlaut fehlt. (ok man kann ja 8 frei definieren, daher nicht so schlimm).
Punkt 2: Es hat aber nur 2 Zeichensätze wenn man es im 4 Bit Modus anspricht! Nämlich englisch_russisch und englisch_japanisch. Beide westeuropäischen fallen weg. :( Sollte man die trotzdem auswählen schaltet das Display in den Grafikmodus. 8 Bit gehen alle 4, wär mir aber zu viel zu verkabeln.

Aber ich wollte das am liebsten später eh im Grafik Mode betreiben (100x16px hat es).
Hat das schon mal jemand gemacht?
 
Und noch eine Notiz:

Hab versucht benutzerdefinierte Zeichen (CGRAM) zu erstellen und verwenden (eben wegen den fehlenden Umlauten).
Stunden- und Tagelang gesucht weil nach dem Definieren der Zeichen das Display immer schwarz blieb.

Wenn man die Zeichen definiert müssen die oberen 3 Bits (die ja eigentlich nicht genutzt werden) auf 1 gesetzt werden, nicht auf 0! Laut Datenblatt ist das egal ob 1 oder 0... Hab ich gemerkt wie "not relevant" das ist...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)