Hallo Community, ich habe ein Problem mit meinem OLED-Display. Ich versuche seit Tagen es vernünftig zum Laufen zu bringen. Programmieren tue ich es in C mit dem AVR-Studio 6. Laufen soll es auf einem Atmega8. Es handelt sich um ein OLED von electronic Assembly (Typ EA W082-XLG) Was funktioniert schon? -Ich bekomme es Initialisiert. Alles okay. -Ich kann auch was ausgeben. Läuft :-) -Cursor lässt sich an gewünschte Position verschieben (Auch in 2. Zeile) Was ist mein Problem? - wenn ich dem Cursor verschoben habe, lässt sich nix mehr schreiben egal in welcher Zeile und Position... Habt ihr da eine Idee? Wenn das Programm (siehe Anhang) läuft, sieht die Ausgabe am Display so aus: ########## #12341234# #12341234# ########## Der Cursor rutscht irgendwann in die Zweite Zeile und schreibt auch diese voll. Es scheint also richtig Initialisiert zu sein. Ich sehe ihn immer durchwandern und Stellen überschreiben. Sorry schonmal für die eventuell unsaubere Programmierung. Bin noch ziemlicher Neuling, was die µC-Welt angeht.
:
Verschoben durch Moderator
Nachdem ich mich jetzt registriert habe, melde ich mich nochmal dazu. Ich habe den Fehler jetzt lokalisiert, konnte ihn aber noch nicht endgültig beheben. Es liegt an meiner Busy-Flag Abfrage. Da kommt er nicht mehr raus und bleibt hängen. Habe das Programm modifiziert und es läuft prima. Aber eben nur, wenn ich die Abfrage komplett weg lasse und überall kurze Verzögerungen im µs-Bereich einbaue. So die optimale Lösung ist es natürlich nicht. hier mal der Code-Schnippel, der nicht funktioniert:
1 | uint8_t BusyZustand = 0b00000000; |
2 | uint8_t BusyHIGH =0b10000000; |
3 | uint8_t BusyErgebnis = 0b10000000; |
4 | |
5 | //-----------------------------------
|
6 | //----- Busy zyklisch checken
|
7 | //-----------------------------------
|
8 | void BusyAbfrage(void) |
9 | {
|
10 | BusyZustand = 0b00000000; |
11 | BusyHIGH =0b10000000; |
12 | BusyErgebnis = 0b10000000; |
13 | |
14 | while(BusyErgebnis>0) |
15 | {
|
16 | DDRD = 0x00; |
17 | DDRB |= ( 1 << PB0 )|( 1 << PB1 ); // PB0, PB1 als Ausgang setzen |
18 | PORTB &= ~(1<<PB0); //löschen (PBo auf NULL setzen) |
19 | PORTB |= (1<<PB1); //PB1 auf EINS setzen |
20 | //RS = 0
|
21 | //RW = 1
|
22 | BusyZustand=PIND; |
23 | wartemikrosekunden(5); |
24 | BusyErgebnis= BusyZustand & BusyHIGH; |
25 | }
|
26 | }
|
In jedem Programmteil, wo ich dann neue Befehle ans OLED sende, wollte ich dann zuerst
1 | BusyAbfrage(); |
durchführen. Und das funktioniert leider nicht. Habt ihr eine Idee, woran es liegen könnte? Grüße
Ein guter Einwand :-) Habe es gerade ausprobiert... bringt aber keine Besserung. Getestet mit 2 und 3 EN-Pulsen. So habe ich es probiert:
1 | void BusyAbfrage(void) |
2 | {
|
3 | BusyZustand = 0b00000000; |
4 | BusyHIGH =0b10000000; |
5 | BusyErgebnis = 0b10000000; |
6 | |
7 | while(BusyErgebnis>0) |
8 | {
|
9 | DDRD = 0x00; |
10 | DDRB |= ( 1 << PB0 )|( 1 << PB1 ); // PB0, PB1 als Ausgang setzen |
11 | PORTB &= ~(1<<PB0); //löschen (PBo auf NULL setzen) |
12 | PORTB |= (1<<PB1); //PB1 auf EINS setzen |
13 | //RS = 0
|
14 | //RW = 1
|
15 | wartemikrosekunden(5); |
16 | PORTB |= (1<<PB2); // EN = 1 |
17 | wartemikrosekunden(5); |
18 | PORTB &= ~(1<<PB2); // EN = 0 |
19 | wartemikrosekunden(5); |
20 | PORTB |= (1<<PB2); // EN = 1 |
21 | wartemikrosekunden(5); |
22 | PORTB &= ~(1<<PB2); // EN = 0 |
23 | wartemikrosekunden(5); |
24 | PORTB |= (1<<PB2); // EN = 1 |
25 | wartemikrosekunden(5); |
26 | PORTB &= ~(1<<PB2); // EN = 0 |
27 | wartemikrosekunden(5); |
28 | |
29 | BusyZustand=PIND; |
30 | wartemikrosekunden(5); |
31 | |
32 | BusyErgebnis= BusyZustand & BusyHIGH; |
33 | }
|
34 | }
|
Martin B. schrieb: > So habe ich es probiert: Nö. Du setzt EN auf 1, liest das Busy-Flag, setzt EN wieder auf 0. Und das wiederholst du so lange wie das Busy-Flag 1 ist.
GENIAL!!! Jetzt läuft es. Vielen Dank!! Bei mir reichen zwei Impulse. Mit einem ging es nicht. Ich habe es mir doch gedacht, da ist nur ein einfacher Denkfehler drin. Danke Stefan, hast mir den Abend gerettet! Sieht jetzt so aus:
1 | void BusyAbfrage(void) |
2 | {
|
3 | BusyZustand = 0b00000000; |
4 | BusyHIGH =0b10000000; |
5 | BusyErgebnis = 0b10000000; |
6 | |
7 | while(BusyErgebnis>0) |
8 | {
|
9 | DDRD = 0x00; |
10 | DDRB |= ( 1 << PB0 )|( 1 << PB1 ); // PB0, PB1 als Ausgang setzen |
11 | PORTB &= ~(1<<PB0); //löschen (PBo auf NULL setzen) |
12 | PORTB |= (1<<PB1); //PB1 auf EINS setzen |
13 | //RS = 0
|
14 | //RW = 1
|
15 | wartemikrosekunden(5); |
16 | |
17 | PORTB |= (1<<PB2); // EN = 1 |
18 | wartemikrosekunden(5); // warte 5µs Ausgang stabilisieren |
19 | BusyZustand=PIND; //Busy-Flag abholen |
20 | PORTB &= ~(1<<PB2); // EN = 0 |
21 | |
22 | PORTB |= (1<<PB2); // EN = 1 |
23 | wartemikrosekunden(5); // warte 5µs Ausgang stabilisieren |
24 | BusyZustand=PIND; //Busy-Flag abholen |
25 | PORTB &= ~(1<<PB2); // EN = 0 |
26 | |
27 | |
28 | BusyErgebnis= BusyZustand & BusyHIGH; |
29 | }
|
30 | }
|
Schon mal nachgemessen ob der Busy Check sich überhaupt lohnt? Ich finde die Delay Methode besser. Dann läuft die Schaltung auch ohne Display wenn es sein muss;)
Bin mir nicht sicher, wie ich das beantworten soll.... Mit der Delay-Methode habe ich stabilen Betrieb hinbekommen, indem ich nach jedem Befehl 5µs gewartet habe. Und wirklich nach Jedem. (Befehl senden, Zeichen/Zeichenkette senden, DisplayClear, Cursor-Modus ändern usw...) Jetzt mache ich die Busy-Abfrage und pulse 2mal das EN-Signal mit jeweils 5µs. Die ENABLE-Zeiten kann man sicher noch etwas verkürzen. Das werde ich noch testen. Aber im großen Ganzen wird es sich wohl die Waage halten. Für meine Zwecke sind diese Verzögerungen aber nicht wild. Bin ja noch am Anfang und "spiele" :-)
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.