Forum: Mikrocontroller und Digitale Elektronik 8-Bit Display Ansteuerung


von Chris H. (chris_hag)


Angehängte Dateien:

Lesenswert?

Guten Morgen,

ich versuche gerade eine Art Allgemeine Fernsteuerung mit diversen 
Eingabeelementen und einem 4x20 Display von der DST-GmbH (AV2040 ==> 
http://www.dst-gmbh.de/anag%20vision%20cm.htm)aufzubauen. Damit sollen 
über z.B. über TWI diverse andere Projekte angesteuert werden.

Dabei will ich mein Code soweit Modularisieren, wie es möglich ist und 
dementsprechend auch eigene Bibliotheken aufsetzen.

Die Eingabeelemente (Taster, Poti und Stick) funktionieren soweit 
perfekt. Das Problem ist nur das Display welches aus irgendwelchen 
Gründen nicht funktionieren will.

Die Tutorials bin ich schon durch und die Daten werden auch korrekt aus 
dem Atmega 32 gesendet, was mein Bus-Analyser auch bestätigt. Ein 
Problem an der Schaltung ist also eher unwahrscheinlich, jedoch nicht 
unmöglich ;-)

Deswegen gehe ich von Code aus. (Siehe Anhang)
In der Main in einem anderen Modul wird das Display Initialisiert, was 
mit einer LED bestätigt wird. (Die DisplayFunction.cpp wird zumindest 
erfolgreich aufgerufen). Alle erforderlichen Pins sind als Ausgang 
gesetzt.

jetzt kann es sein, dass mir nur ein kleiner logischer Fehler 
unterlaufen ist oder ich jedoch etwas elementares Wichtiges vergessen / 
nicht beachtet habe.

Über jede Hilfe wäre ich sehr erfreut.

Wenn etwas zu Klärung des Falles fehlen sollte, dann werde ich es gerne 
schnellst möglich nachreichen.

Vielen Dank an die Community.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christian Hagemeyer schrieb:
> Wenn etwas zu Klärung des Falles fehlen sollte, dann werde ich es gerne
> schnellst möglich nachreichen.

Wie wär's mit einer Beschreibung des Fehlers?

von m.n. (Gast)


Lesenswert?

//Alle Displayausgänge auf Low stellen
  Display = 0x00;

Was ist Display?

von Chris H. (chris_hag)


Lesenswert?

Ach ja. Sorry, die Fehlerbeschreibung fehlt.

Im allgemeinen Funktioniert das Display nicht. Anscheinend lässt es sich 
nicht initialisieren.

Die Spannung an V0 des Displays beträgt ca. 4V (natürlich mit Poti 
einstellbar).

Im Grunde zeigt die Anzeige nur nichts an.
Habe auch kein zweites um Fehler an der Hardware auszuschließen.

@m.n.: Display ist definiert für den kompletten Port D des 
Mikrocontrollers. Das macht das Ansprechen und leichter und steigt bei 
mir die Übersicht in dem Programm. sprechende Namen und so ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christian Hagemeyer schrieb:
> Im Grunde zeigt die Anzeige nur nichts an.

Geht der typische schwarze Balken weg, der beim Einschalten (ohne
irgendwelche Firmware-Interaktion) sichtbar ist?

von m.n. (Gast)


Lesenswert?

Christian Hagemeyer schrieb:
> @m.n.: Display ist definiert für den kompletten Port D des
> Mikrocontrollers.

Und ist PortD auch als Ausgang initialisiert?
Dem  Programmschnipsel ist das leider nicht zu entnehmen.

von Chris H. (chris_hag)


Lesenswert?

Ja. Beide Balken in Zeile 1 und 3 sind erst sichtbar und verschwinden 
dann.

von spess53 (Gast)


Lesenswert?

Hi

>Die Spannung an V0 des Displays beträgt ca. 4V (natürlich mit Poti
>einstellbar).

4V, oder besser 4,1..4,7V, ist aber die Spannung zwischen V0 und VCC. 
Nach Masse gemessen sind das 0,3...0,9V.

MfG Spess

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christian Hagemeyer schrieb:
> Ja. Beide Balken in Zeile 1 und 3 sind erst sichtbar und verschwinden
> dann.

Dann funktioniert die Initialisierung, das ist doch schon mal ein
Schritt.

von Eric B. (beric)


Lesenswert?

Zwar nicht Ursache für das beschriebene Problem, aber trotzdem --
Im Code gefunden:
1
  switch(Zeichen)
2
  {
3
    case ' ': Display_Data_Write(0x20); break;
4
    case 'A': Display_Data_Write(0x41); break;
5
    case 'B': Display_Data_Write(0x42); break;
6
...
7
    case '#': Display_Data_Write(0x23); break;
8
    case '_': Display_Data_Write(0x5f); break;    
9
  }
Dir ist klar dass ' ' das gleiche ist wie 0x20? Und dass genau so bei 
'A' und 0x41, usw?

Mit dem Erkenntniss reduziert sich dein Riesen-switch/case nämlich auf 
eine einzelne Zeile Code:
1
Display_Data_Write(Zeichen);
(Ok, da fehlt dann der Test ob Zeichen im gültigen Wertebereich liegt)

von Chris H. (chris_hag)


Angehängte Dateien:

Lesenswert?

@m.n.: Ja, das habe ich mit folgende Anweisungen gemacht:
(hier auch noch gleich die 3 Steuerpins)

DDRD = 0xff;         //Display-output
DDRB |= (1<<LCD_RW_DDRB0);  //Display Steuerung Output
DDRC |= (1<<LCD_RS_DDRC6) | (1<<LCD_Enable_DDRC7); //Display Steuerung 
output

@spess53: Die einzelnen Spannungen betragen bei meiner Betriebsspannung 
von ca. 4,96V:
von V0 ==> Masse (VSS) ca. 0,39V
von V0 ==> UBat (VDD) ca. 4,5V

@Jörg Wunsch: Also könnte etwas in der Grundeinstellung falsch sein.

@Eric B.: Danke für den Hinweis. Werde es für den nächsten Schritt, der 
Codeoptimierung berücksichtigen.

Anbei hänge ich noch die Auswertung der Datensignale an. Evtl. hilft das 
weiter.

von Pandur S. (jetztnicht)


Lesenswert?

Allenfalls gibt es noch Timing bedingungen, dass man nicht zu schnell 
schreiben kann. Ich schreib zB alle 10ms mit meinem TimerTick ein 
einzelnes Zeichen.

von Dieter F. (Gast)


Lesenswert?

Ich würde mir mal im Datenblatt die Initialisierungssequenz für den 
KS0066 anschauen uns das auch so programmieren. Die sieht nämlich etwas 
anders aus ...

http://html.alldatasheet.com/html-pdf/37318/SAMSUNG/KS0066/6495/26/KS0066.html

Stimmt deine F_CPU-Angabe (ich gehe davon aus, die existiert ... wegen 
delay...) mit dem tatsächlichen Takt überein?

von spess53 (Gast)


Lesenswert?

HI

>Ich würde mir mal im Datenblatt die Initialisierungssequenz für den
>KS0066 anschauen uns das auch so programmieren. Die sieht nämlich etwas
>anders aus ...

Bei mir besteht die ganze Initialisierung für 8-Bit-Mode aus genau 
vier Kommandos:

40ms Warten

0x38 Functionset: 8Bit/2line/5x8 Zeichen

8ms Warten

0x0c Disp on/Cursor off/no blink
0x01 Display löschen
0x06 Entry Mode: Cursor inc/Cursor move

Fertig.

MfG Spess

von Pandur S. (jetztnicht)


Lesenswert?

Bei 2 Zeilern muss man fuer die 2. Zeile ueblicherweise den Cursor auf 
hex 40 setzen.

: Bearbeitet durch User
von Chris H. (chris_hag)


Lesenswert?

@Jetzt Nicht: Danke. Habe den uCount auf 10 µs gestellt und es wird 
etwas angezeigt.

Also stimmen die angegebenen Zeiten in dem Datenblatt nicht richtig, da 
ich mich eigentlich daran gehalten habe, was drin steht (zumindest Zeit 
technisch)

Kann mir bitte jemand folgendes noch erklären:

Im Datenblatt steht für die Executing Time (FOSC = 270kHz). Woher wird 
diese Frequenz genommen? Mein Atmega läuft ja über 16MHz.

Im Datenblatt sind leider keine internen Schaltungen enthalten. Nur 
folgende Formel:
Example: wenn FOSC = 270kHz dann gilt folgendes: 40µs * ( 250 / 270) = 
37µs.

Mathematisch ist das schon richtig, wenn ich davon ausgehe, dass es sich 
im Zähler um 250 kHz handelt und die 40µs stellvertretend für die 
einzelnen Ausführungszeiten der Kommandos ist.

Wo ist da der Zusammenhang?

von m.n. (Gast)


Lesenswert?

Dieter Frohnapfel schrieb:
> Ich würde mir mal im Datenblatt die Initialisierungssequenz für den
> KS0066 anschauen uns das auch so programmieren. Die sieht nämlich etwas
> anders aus ...


Als Pause zwischen den Initwerten nehme ich 10 ms, was sich im Laufe der 
Jahrzehnte als sinnvoll erwiesen hat. Ein zu knappes Timing gab immer 
Probleme!

Christian Hagemeyer schrieb:
> Im Datenblatt steht für die Executing Time (FOSC = 270kHz). Woher wird
> diese Frequenz genommen? Mein Atmega läuft ja über 16MHz.

Das Timing ist LCD-intern, wackelt zudem mit der Versorgungsspannung und 
hat mit dem ATmega nichts zu tun. Im Zweifelsfall warte keine 40 µs 
sondern besser 100 µs.
Da Du R/W als separate Leitung zur Verfügung hast, kannst Du auch den 
Status der Anzeige abfragen, bevor ein neues Zeichen auszugeben ist. Das 
ist die schnellste Variante.

von Dieter F. (Gast)


Lesenswert?

Christian Hagemeyer schrieb:
> Mathematisch ist das schon richtig, wenn ich davon ausgehe, dass es sich
> im Zähler um 250 kHz handelt und die 40µs stellvertretend für die
> einzelnen Ausführungszeiten der Kommandos ist

Ich bin jetzt nicht Mister Ober-Display (da gibt es hier andere 
Kapazitäten :-) ) - aber die Angabe 270 kHz  bezieht sich auf die 
mittlere Taktfrequenz des Display-Conrollers. Die angegebenen 
Wartezeiten sind darauf abgestimmt.

Wenn man dann im Datenblatt etwas herumsucht sieht man auch

Internal Clock
(external Rf)
fOSC1
Rf = 91 kW + 2%
(VDD = 5 V) 190 270 350 kHz

dass das schwanken kann (min. 190 med. 270 max. 350).

Deshalb tut man gut daran, auf die angegebenen Wartezeiten einen kleinen 
Zuschlag zu geben ...

von Pandur S. (jetztnicht)


Lesenswert?

Ah. Ja. Und die Ready Leitung verwende ich nicht, da ich mit konstantem 
grosszuegigem Timing arbeite. Man sollte immer bedenken, der Benutzer 
kann keine 10 Updates oder mehr pro Sekunde ablesen. Heisst schneller 
als 1ms pro Zeichen macht keinen Sinn.
Ich habe meinen Screenbufer im Ram, und schiebe den mit dem Timer stur 
Zeichen fuer Zeichen in das LCD, auch solche Zeichen, die sich nicht 
aendern, oder die blank sind.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Im Datenblatt steht für die Executing Time (FOSC = 270kHz). Woher wird
>diese Frequenz genommen? Mein Atmega läuft ja über 16MHz.

Das ist die Taktfrequenz des Displaycontrollers. Zulässig sind 190...350 
kHz.

MfG Spess

von Chris H. (chris_hag)


Lesenswert?

@Dieter Frohnapfel: habe mir das Datenblatt angeschaut und mit dem von 
meinem Display verglichen.

Im Grunde ist es fast gleich, nur das die Zeiten anders sind und bei 
meinem Datenblatt 3x der Hex-Wert 0x30 gesendet werden muss mit jeweils 
anderen Zeiten dazwischen. (erst 30ms warten; dan n4,1µs; dann 100µs und 
dann fehlen dort die Zeitangaben)

Und die Einstellungen passieren erst nach dem 3.ten Zyklus.

m.n. schrieb:
> Da Du R/W als separate Leitung zur Verfügung hast, kannst Du auch den
> Status der Anzeige abfragen, bevor ein neues Zeichen auszugeben ist. Das
> ist die schnellste Variante.

Das war meine Absicht, nur musste ich wissen, ob das LCD überhaupt erst 
mal funktioniert. (Also Datenleitungen richtig angeschlossen, Code 
richtig erkannt und ausgeführt und kein Hardwareschaden ;-) )

Also Zusammenfassend ist das Datenblatt nicht aussagekräftig genug 
gewesen (Oder ich zu Blöd) Dafür lernt man

von Dieter F. (Gast)


Lesenswert?

Christian Hagemeyer schrieb:
> bei
> meinem Datenblatt 3x der Hex-Wert 0x30 gesendet werden muss mit jeweils
> anderen Zeiten dazwischen. (erst 30ms warten; dan n4,1µs; dann 100µs und
> dann fehlen dort die Zeitangaben)

Was ist das denn für ein Datenblatt? Für Dein Display sllte es nur ein 
Datenblatt - nämlich das für den verbauten KS0066-Display-Controller 
geben.

Irgendein anderes Datenblatt ... ist sicher interessant zu Lesen :-), 
aber nicht unbedingt sinnvoll ...

von m.n. (Gast)


Lesenswert?

Aus Spaß kannst Du abschließend auch den 4-Bit Modus probieren. Dabei 
wirst Du sehen, daß die Ausgabe nicht langsamer ist aber 4 Portleitungen 
gespart werden. Die Wartezeit für eine Zeichen-/Befehlsausgabe ist erst 
nach erfolgter Ausgabe des 8-Bit Wertes fällig. Die einzelnen Nibble 
können ohne Verzögerung direkt nacheinander geschrieben werden.

Noch einmal zur Betonung: das Busy-Flag (BF) immer vor einer neuen 
Ausgabe abfragen. Im Idealfall entsteht dann keine zusätzliche 
Wartezeit.
Diese Regel gilt eigentlich auch fürs EEPROM-Schreiben, wird aber immer 
wieder aus Unachtsamkeit mißachtet.

von Dieter F. (Gast)


Lesenswert?

Dieter Frohnapfel schrieb:
> Irgendein anderes Datenblatt ... ist sicher interessant zu Lesen :-),
> aber nicht unbedingt sinnvoll ...

O.K., nehms zurück :-) - steht in Deinem Link so drin. Interessant ...

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
Noch kein Account? Hier anmelden.