www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD ansteuern, fragen zu tutorial in assembler


Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nabend,

also, ich habe mir nun bei pollin ein LCD NAN YA LMK62R gekauft.
Ich habe es an meinen AT89S52 angeschlossen.
Wenn ich Vcc anlege, dann erscheint der obere Balken in schwarz.
Es scheint also schonmal anzugehen ;)

So, nun bin ich dabei zu verstehen, wie man das Display ansteuert.
 Das man, wenn man im 4 bit modus arbeitet, die 8 bit aufteilen und dann 
in 2 nibbles senden muss habe ich wohl verstanden. Dafür setze ich die 
ausgänge auf den wert den ich gern hätte und dann einmal kurz E=1 kurz 
warten und dann E=0.

Soweit so gut.
Um allerdings den rest zu vestehen, müsste ich wohl einigermaßen 
assembler können...denn das AVR LCD tutorial nutzt diese sprache.
Ich würde es allerdings gern in C machen.

Gibts dafür eine gute Seite? Unter den weblinks find ich leider nix.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Oliver D. (highspeed-oliver)

>assembler können...denn das AVR LCD tutorial nutzt diese sprache.
>Ich würde es allerdings gern in C machen.

Gibts doch auch alles.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

MfG
Falk

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ich glaube bei sprut.de bin ich fündig geworden :)

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh cool.

Ich hatte bei artikel suche LCD eingetippt. In LCD bin ich dann unten 
auf AVR LCD gegangen...

Wer suchet der findet ;)

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, bei dem AVR GCC tutorial ist es natürlich für den AVR...somit 
müsste ich mich überall durchwursten.
Ich glaube da ist es schlau mit Anleitung erstmal selber zu 
programmieren.
Das AVR GCC tut ist für meine C kenntnisse ziehmlich riesig.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Oliver D. (highspeed-oliver)

>Hmm, bei dem AVR GCC tutorial ist es natürlich für den AVR...somit
>müsste ich mich überall durchwursten.

????
Es werden lediglich schreibende Portzugriffe gemacht. Der Rest ist 
Standard-C. Das sollte in Null Komma Nix an den 89er anpassbar sein.

>Das AVR GCC tut ist für meine C kenntnisse ziehmlich riesig.

Du braucht nicht mal einen Bruchteil.

MfG
Falk

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mag sein, dass ich nur einen bruchteil brauche....da ich aber noch 
garkeine ahnung habe und auch niemanden der es mir am pc erklären kann, 
ist das schon eine kleine herausforderung.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, wenn ich das AVR GCC tutorial an meinen at versuche anzupassen, 
kriege ich ooohne ende fehler....

z.B. void set_cursor(uint8_t x, uint8_t y);

das kommt in die lcd_routines.h  Als fehler erhalte ich Invalid 
parameter declaration.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist mit

#define LCD_DDR

gemeint?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Oliver D. (highspeed-oliver)

>z.B. void set_cursor(uint8_t x, uint8_t y);

>das kommt in die lcd_routines.h  Als fehler erhalte ich Invalid
>parameter declaration.

Da fehlt wahrscheinlich

#include <stdint.h>

>Was ist mit
>#define LCD_DDR
>gemeint?

Das ist das Data Direction Register, welches festlegt, ob ein Bit eines 
Ports Ein- oder Ausgang ist.

MfG
Falk

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Fehler bleibt bestehen.
Invalid parameter declaration.

Das Data direction register sitzt doch im avr nicht wahr?
Sowas hat mein AT89S52 garnicht.
Meine ich.... Ich kann einfach einen portpin auf masse ziehen um einen 
zweiten zustand zu haben. Vorher schreibe ich einfach eine 1 rein. Der 
Taster z.b. zieht die 1 dann auf masse.

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja da hast du Recht, du musst nur die Daten ausgeben ein DDR hat der 
AT89S52 nicht. Deshalb bringt dir das auch nicht wirklich was die Zeilen 
aus dem Tutorial zu kopieren.

Was hast du denn für nen Compiler?
Versuch doch einfach das Tutorial zu lesen und zu verstehen. Dann kannst 
du das in 0,nix für deinen uC umsetzen.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ja, ich versuche natürlich das zu verstehen.

Mir würde es reiche, wenn ich zumindest das display schonmal 
initialisiert bekommen. Dafür gibt es bei sprut.de ein ablaufdiagramm, 
wo was geschrieben werden muss um das display in den 4 bit modi zu 
bekommen.
Das habe ich programmiert und auf den uc geschrieben, aber es wird nur 
der oberste reihe meines LCDs eingeschaltet.

Eigentlich sollten das dann doch beide sein.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein compiler ist der RIDE von raisonance

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nee, wenn man Spannung anlegt, leuchtet je Nach Display immer nur ein 
Teil.

z.B. die erste Zeile, erste und dritte, die erste Hälfte der Zeile,...

Deine Initialisierung funktioniert nicht sonst würde es nur kurz 
aufblinken und dann leer sein.

Da stimmt bestimmt das Timing nicht.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok.

Ich meine aber alle zeiten eingehalten zu haben und eher ein bischen zu 
viel zu haben....

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, dann stell doch mal nen Schaltplan und das Programm hier rein. Das 
Datenblatt des LCD ist ja eher dürftig...

Autor: Hannes Lux (hannes)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oliver D. wrote:
> Ok.
>
> Ich meine aber alle zeiten eingehalten zu haben und eher ein bischen zu
> viel zu haben....

Vielleicht hilft Dir das ja weiter...

...

Autor: Oliver D. (highspeed-oliver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ehm schaltplan?

Ich habe das Display so verbunden:
sbit  DB4=0xB0;
sbit  DB5=0xB1;
sbit  DB6=0xB2;
sbit  DB7=0xB3;
sbit  RS=0xB4;
sbit   E=0xB5;

Also einfach an Port B0 das dingen angeklemmt.
RW liegt auf masse.

Mein Board funktioniert 100% einwandfrei.

Die Verkabelung zum Display ist ebenfalls einwandfrei. Habs 
durchgemessen.
Ich habe ausserdem ein zweites Display hier, was sich mit gleichem code 
ebenfalls nicht inititalisieren lässt.
Liegt dann wohl an meinem code ;)

Ich habe den mal in den Anhang gepackt. Wundert euch nicht, dass es 
absoluter Mist vom Stil her ist...Es ist einfach mal für den Anfang 
gedacht um einfach das Display mal zu initialisieren.
Für die Zeit habe ich einfach mal eine For schleife genommen.
Achja, mein uC läuft bei 11,0592Mhz.

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie gesagt, das Timing stimmt nicht.

Näach anlegen der Betriebsspannung >=15ms warten...
Deine Warteschleifen werden wohl auch wegoptimiert und dann fehlt auch 
noch enable in deinem Code.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Enable?

Mir fällt gerade auch auf, das beim Beispiel programm code des AVR GCC 
ein kurzer Enable Impuls eingetragen ist. Dieser wird scheinbar immer 
dann ausgefüht, wenn ein Wert übernommen werden soll?!?!

Im Tutorial von Sprut.de steht aber nur, das sich bei 1 Signal auf E das 
Display ansprechen lässt.

Achja, muss ich unbedingt eine LCD Clear routine ausführen, damit nach 
dem initialisieren der balken verschwindet? Oder geht der automatisch 
weg?

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Halt ich für ein Gerücht, das steht da nicht. Nach der Initialisierung 
ist das Display leer, da siehst du ob es funktioniert hat. Das pdf von 
Hannes ist auch ganz toll.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das mag sein.

Naja ich glaube nach 3 stunden rumprobiererei...

Jedenfalls währe es schön einfach mal ein einfaches beispiel nur zur 
initialisierung zu haben.
Gibts nicht irgendeine gute website auf der sowas für "anfänger" 
geschrieben ist?

Ich finde den code sehr groß, vor allem weil in jeder funktion wieder 
eine andere aufgerufen wird etc.

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja hier das Tutorial auf der Seite. Die Fehler, die oben auftauchen, 
liegen an deinem compiler. Der hat bestimmte Definitionen des gcc nicht 
bzw. andere. Wenn du keine Programmiererfahrung hast, dann solltest du 
erstmal mit ASM loslegen oder das Handbuch zu dem Compiler lesen. Ach 
und fang bei Schritt 1 an. LED Blinken lassen im 2Hz Rhythmus, dann 2 
LED blinken lassen und zwar gleichzeitig und dann mal entgegengesetzt. 
Das erspart dir viel Zeit und Frust...

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm,

also in C bekomme ich sowas bereits hin.
Mit Timer etc. Auch Interruptroutinen kann ich programmieren.

Z.b. eine Ampelschaltung mit LEDs. BEi Interrupt wird dann den 
Fußgängern das überqueren ermöglicht...
solche spielereien.

Asm möchte ich mir einfach nicht antun.
Ich werde für meine Prüfung ohnehin nur c brauchen, da muss man nicht 
noch soetwas lernen.

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist ehrlich schwer vorstellbar mit Ampel und Interrupt...
Also ich kann kein C und find das alles recht gut und easy im Tut. 
erklärt.
ASM "antun", man glaubt garnicht wie hilfreich das manchmal sein kann.

Erst wird die Funktion jedes Pins des LCD erklärt, übrigens auch bei 
sprut.
Und dann die einzelnen Funkionen..


void lcd_data(unsigned char temp1);

sendet Daten an das Display

void lcd_command(unsigned char temp1);

sendet einen Befehl an das Display

void lcd_enable(void);

// erzeugt den Enable-Puls

void lcd_init(void);
// Initialisierung:
// Muss ganz am Anfang des Programms aufgerufen werden.

usw.
void set_cursor(uint8_t x, uint8_t y);
die Funktion macht nen Error weil dein Compiler wohl uint8_t nicht kennt 
aber die Funktion brauchst du eh noch nicht.


also


void lcd_init(void)
{
   LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN);   // Port auf 
Ausgang schalten

-> brauchst du nicht
   // muss 3mal hintereinander gesendet werden zur Initialisierung

   _delay_ms(15); hm, wie lautet die warte 15ms Funktion in Ride?
->   So jetzt werden die Pins gesetzt.
   LCD_PORT &= 0xF0;
   LCD_PORT |= 0x03;
   LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0

-> Enable Puls
 lcd_enable();

   _delay_ms(5);
->Warten


usw.....


jetzt kannst du das doch für deines anpassen.

void display_init (void)
{
wait (50);   -> ersetzen durch warteschleife 40ms
E=0;         // Enable ausschalten
//initialisieren  f�r 4 bit
RS=0; //Steuerregister auswählen
DB7=0; //Datenleitungen einstellen
DB6=0;
DB5=1;
DB4=1;
E=1;  //Enable Leitung triggern
wait (1us); //kleine Pause
E=0;

.....

So. unt wenn du schon mit Interrupts gearbeitet hast, dann kannst du ja 
den Timerinterrupt nutzen um die Pause zu machen, falls dein Compiler 
keine wartefunktion hat.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Asm möchte ich mir einfach nicht antun.

Schade eigentlich. Denn der Controller kann kein C, der kann nur 
Maschinencode, der einszueins nur in Assembler notiert werden kann. Mit 
C alleine kommst Du vielleicht unter einem Betriebssystem zurecht, bei 
Mikrocontrollern ist man aber sooooo dicht an der Hardware, dass 
Assemblerkenntnisse schon erforderlich sind. Die Leute, die gute 
C-Programme für Mikrocontroller schreiben, die können auch alle 
Assembler.

...

Autor: Oliver D. (highspeed-oliver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ja, könnte ich machen ;)

Also zu dem enable.
Wenn ich daten an den controller schicken will muss ich zunächst auf E=0 
schreiben.
Dann kurz warten.
Dann in RS und RW=0 schreiben.
kurz warten.
Dann E=1 setzen.
Jetzt gebe ich meine steuerbefehle auf die Leitung.
kurz warten.
E=0 setzen. Mit der negativen Flanke werden die steuerdaten übernommen.

Ist das so korrekt?
Das brauche ich ja dann quasi immer, weil nur dann daten vom HD 
controller bearbeitet werden.

Achja, bei Sprut.de ist eine tabelle für den HD controller, wie man in 
den 4 bit modus kommt. (im anhang)

Wenn ich das schritt für schritt genauso nachprogrammiere, müsste mein 
display doch initialisiert sein, oder?
Natürlich mit dem zwischenschritt, dass ich die daten immer nur per 
wechsel von E auf 0,1,0 in den Controller reinbekomme.

Korrekt?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich das schritt für schritt genauso nachprogrammiere, müsste mein
> display doch initialisiert sein, oder?

Du kannst programmieren was Du willst, wenn Du das Verhalten Deines 
Compilers nicht kennst, kommt sowiso was anderes raus als Du denkst 
programmiert zu haben.

Ich kann kein C, ich programmiere in Assembler, aber nur AVRs. Man liest 
hier aber immer wieder, dass C-Compiler Warteschleifen wegoptimieren und 
auch sonst ein gewisses Eigenleben entwickeln. Einziger Weg, Sicherheit 
zu haben, ist das Überprüfen des vom C-Compiler erzeugten 
Assemblercodes, dazu sollte man aber etwas Assembler können.

Nächster Punkt: Du benutzt einen relativ schnellen Quarz. Könnte es 
sein, dass das Timing deshalb nicht einzuhalten ist? Highspeed ist nicht 
immer der beste Weg...

Im Übrigen habe ixch den Eindruck, dass Du hier völlig orientierungslos 
mit Versuch und Irrtum experimentierst, anstatt die Sache mal 
systematisch anzugehen. Im von mir weiter oben geposteten 
Pollin-Datenblatt (in Deutsch) sind in Kurzfassung die Algorithmen zur 
Initialisierung beschrieben. Du musst sie nur noch in der 
Programmiersprache Deiner Wahl umsetzen und dabei das Timing einhalten. 
Wenn Du aber zuviele Baustellen gleichzeitig hast, also weder den 
Algorithmus verstehst, noch mit Deiner Programmiersprache umgehen 
kannst, dann hast Du schlechte Karten, dann solltest Du wirklich nochmal 
mit kleineren Projekten beginnen, die Aussicht auf Erfolg haben, um 
durch Training sattelfest zu werden.

...

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also erst Daten anlegen, dann einmal enable auf 1, kurz warten wieder 
auf 0.

Ja wenn du das so programmierst, dann sollte das Display initialisiert 
werden und auch leer sein.

Autor: Olli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgendwo im Datenblatt steht bestimmt, was man dem Display für Signale 
senden muss, damit es funzt.

Diese Funktionen programmierst du dann selber in C (sollte für dich ja 
kein problem sein, nach der Ampelsteuerung)

Dann noch was zum Thema for-Schleifen optimierung: Den Grad der 
Optimierung kann man in der Regel einstellen. Wenn du Wartezeiten mit 
for-Schleifen programmierst, ist es ratsam ohne Optimierung zu arbeiten, 
da diese sonst wegoptimiert werden.

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes Lux wrote:
> Ich kann kein C, ich programmiere in Assembler, aber nur AVRs. Man liest
> hier aber immer wieder, dass C-Compiler Warteschleifen wegoptimieren und
> auch sonst ein gewisses Eigenleben entwickeln. Einziger Weg, Sicherheit
> zu haben, ist das Überprüfen des vom C-Compiler erzeugten
> Assemblercodes, dazu sollte man aber etwas Assembler können.

"Eigenleben". Hallo. Da wird was optimiert (schneller, kleiner, besser), 
nur weil du die C-Syntax nicht verstehst und noch nie was programmiert 
hast, heisst das nicht das der Compiler etwas falsch macht.
Am besten bleibst du doch bei deinem Assembler, da wirst du nicht vom C 
ueberfordert.

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Olli

schonmal was von volatile gehoert?

Autor: Olli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Stephan

Klaro kenn ich Volatile!!!

Aber ich will doch den Highspeed-Oliver nicht mit solchen Ausdrücken 
verwirren. Der läuft ja mit dem Display schon auf Anschlag.

Nach meiner Meinung ist eine Antwort nur immer so gut, wie sie vom 
Zuhörer verstanden wird!

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Hannes,

ich habe mir natürlich dein Datenblatt durchgelesen.
Dort steht erstmal die eigenschaft mit dem E etwas anders beschrieben, 
als ich das verstanden habe. Z.b. ist dort nirgends die rede von einer 
ansteigenden Flanke, also von low nach high.
Im Internet laß ich, dass ich beim ersten Schritt nach dem ich >15ms 
gewartet habe erst einmal E=0 setze.
Danach lege ich RW und RS auf 0 um zu signalisieren, dass nun daten 
kommen, die ins steuerregister geschrieben werden.
Danach warte ich eine kurze zeit.
Dann setze ich E=1. Mit der steigenden Flanke werden beide werte 
gelesen.
Das Display weiß nun was zu tun ist und mit der nächsten fallenden 
Flanke werden die Werte an DB übernommen.
Dannach soll ich >4,1ms warten.
Danach wieder dasselbe.
E=0. Kurz warten. Dann RS=0 RW=0. Kurz warten. E=1.
kurz warten. An DB 4-7 meine Befehle anlegen, E=0. Es wird übernommen.

Dann warte ich 100us.
Und wieder das gleiche...
 Hiermit habe ich dann 3x D5 und D4 auf 1 gesetzt und den Rest auf Null.

So, nun stelle ich auf 4Bit datenbus um. Dafür schreibe ich eine Hex2 
also 10 rein. DB5 also auf 1 und DB4 auf0. Der Rest liegt auf Null.

Ist für mich bis hierher verständlich.

In deinem text-lcds wird nun der schritt system set ausgeführt. Im 
Tutorial von Sprut.de wird das in 10 Schritten getan. Wohl deshalb, weil 
man ja nun im 4 Bit modus ist und die beiden Nibbles geteilt übertragen 
muss.
Ausserdem wird das display dort noch ein und aus- geschaltet sowie 
gelöscht.


Das letzte was ich dann schreiben müsste währe nurnoch display on.

Dann sollte das Display anspringen...
Ich bin mir eignetlich ziehmlich sicher, dass es dann so funktioonieren 
sollte. Das mit dem  Compiler und wegoptimieren von schleifen kann 
natürlich sein...Ich werde am besten mal einen echten Timer verwenden.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan wrote:
> Hannes Lux wrote:
>> Ich kann kein C, ich programmiere in Assembler, aber nur AVRs. Man liest
>> hier aber immer wieder, dass C-Compiler Warteschleifen wegoptimieren und
>> auch sonst ein gewisses Eigenleben entwickeln. Einziger Weg, Sicherheit
>> zu haben, ist das Überprüfen des vom C-Compiler erzeugten
>> Assemblercodes, dazu sollte man aber etwas Assembler können.
>
> "Eigenleben". Hallo. Da wird was optimiert (schneller, kleiner, besser),
> nur weil du die C-Syntax nicht verstehst und noch nie was programmiert
> hast,

Woher willst Du wissen, ob ich "noch nie was programmiert" habe? Ich 
habe schon einige Dinge programmiert, aber eben nicht in C oder BASCOM, 
sondern in AVR-Assembler. Und natürlich auch nicht für 8051er oder PICs, 
sondern für AVRs. Und ob Du es glaubst oder nicht, meine Programme 
funktionieren, meine LCDs machen das, was sie sollen. Und das alles mit 
eigenem (ASM-)Code, entwickelt aus den Angaben in den Datenblättern, 
also nicht durch Verwendung irgendwelcher Bibliotheken irgendwelcher 
Herkunft.

> heisst das nicht das der Compiler etwas falsch macht.

Das habe ich auch nicht behauptet. Ich habe lediglich behauptet, dass es 
sehr vorteilhaft ist, wenn man seinen Compiler (falls man denn einen 
benutzt) kennen sollte bzw. sein Ergebnis (in ASM) überprüfen sollte.

> Am besten bleibst du doch bei deinem Assembler,

Ja sicher bleibe ich bei Assembler, die von mir benutzten AVRs bleiben 
doch auch bei ASM (bzw. Maschinenvode) und lernen doch auch kein C. 
Assemblerprogrammierung ohne C-Kenntnisse geht ganz gut, 
C-Programmierung ohne ASM-Kenntnisse aber scheinbar nicht oder nur 
begrenzt.

> da wirst du nicht vom C
> ueberfordert.

Da verwechselst Du wohl was... Ich bin nicht der, der Hilfe sucht, Du 
sprichst also den falschen an. Wenn ich ein Verständnisproblem habe, 
dann gehe ich den Dingen auf den Grund, versuche also aus den 
vorhandenen Quellen die nötigen Informationen zu ziehen und die 
Zusammenhänge zu verstehen. Dann bin ich auch in der Lage, mir die 
notwendigen Routinen (in ASM) zu schreiben. Das dauert zwar meist etwas 
länger, hat aber den kleinen Vorteil, dass ich über jedes Byte meines 
Codes Bescheid weiß.

Nichts gegen C, wer es kann, soll damit glücklich werden. Aber wer C 
wirklich kann, der kann auch etwas ASM...

...

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Womit mir immer noch nicht geholfen wäre...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver D. wrote:
> Womit mir immer noch nicht geholfen wäre...

Wenn Du vermutest, dass Dein Compiler die Warteschleifen nicht korrekt 
umsetzt, dann solltest Du Dir als erstes den vom Compiler erzeugten Code 
in ASM anzeigen lassen und überprüfen, ob der Compiler das gemacht hat, 
was Du von ihm erwartest. Solange diese Unsicherheit da ist, lohnt es 
sich nicht, über den Rest nachzudenken.

Und da ich mich (bezüglich Mikrocontroller) nur in der Niesche 
AVR-Assembler auskenne, kann ich Dir auf dem 8051 leider nicht helfen.

...

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ok.

Ich setz mich mal ebend dran mit einem echten Timer die wartezeiten zu 
programmieren.
....

Damit ich den fehler von seiten des compilers her ausschliessen kann.

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probiers doch mal mit volatile:

statt:

int i;
...
for(i=0;i<100;i++);

machst du einfach:

volatile int i;
...
for(i=0;i<100;i++);

und der compiler kuerzt dir nix weg.

Ach ja Hannes, nur weil du auf ASM beschraenkt bist, musst du nicht 
beleidigt sein.

Autor: Oliver D. (highspeed-oliver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, ich habe hier mal was mit timer programmiert.

Ich habe mich dabei zu 100% an die anleitung von sprut.de gehalten.
Es müsste so funktionieren, tut es aber nicht.
Timing ist auch genug drinne!

Autor: Oliver D. (highspeed-oliver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier auch einfach mit volatile.

Funktioniert ebenfalls nicht :(

Autor: Jochen S. (schiffner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo
du hast da was mit dem Enable E falsch verstanden. Du setzt deine 
Datenleitungen und machst dann kurz Enable an, um den Controller zu 
sagen das er die Daten jetzt verarbeiten kann.

E=0;
DB7=0;
DB6=0;
DB5=1;
DB4=1;    //Daten setzen

warten

E=1;
warten
E=0;    // Enable an und aus
warten

nächster Block

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du das an meinem Code erkannt?

Ich dachte das es soo richtig ist.

Erst E=0.
Dann RS=0 und RW=0.
Dann setze ich E=1.
Durch die steigende Flanke + RS und RW nimmt der HD controller an, dass 
nun in steuerregister geschrieben wird.
Dann lege ich an die DBs meine daten an.
Ich setze E=0.
Bei der negativen Flanke werden die Daten eingelesen.

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schon 10mal erwähnt in dem Thread erwähnt, der Display Controller 
übernimmt immer von low nach high die Daten.

Du setzt erst e=1 und änderst dann die Bits und setzt e=0. Erst e=0, 
dann die Bits setzen und dann erst e=1;


void display_init (void)
{
wait (500);
E=0;// E auf 0 Setzen.
//initialisieren  f?it
RS=0; //Interface auf 8 bit setzen
tst_nop();
DB7=0;
DB6=0;
DB5=1;
DB4=1;
tst_nop();
tst_nop();
tst_nop();
E=1;//Bei wechsel von low auf high wird die flanke erkannt und mit 
R/Wlow ein Schreibzugriff sowie mit RS=0
  // die Daten als Kommande verstanden und in den Steuerregister 
geschrieben.
E=0;

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
????

Also das tut mir jetzt leid, dass ich hier etwas falsches schreibe, aber 
auf Sprut.de steht:

Im Moment der Low-High-Flanke von ENABLE liest das Dislplay die Werte 
von RS und R/W ein. Ist zu diesem Zeitpunkt R/W=0, dann liest das 
Display mit der folgenden High-Low-Flanke von ENABLE  den Datenbus ein 
(Schreibzyklus). War aber R/W=1, dann legt das Display ein Datenword auf 
den Datenbus (Lese-Zyklus), solange bis die High-Low-Flanke von ENABLE 
das Interface wieder deaktiviert.

Schreiben zum Display
Die folgende Abbildung zeigt einen Schreibzugriff auf ein Display. Das 
Display überwacht den Pegel von ENABLE. Ändert sich dieser Pegel von Low 
nach High, dann fragt es die Leitungen RS und R/W ab. Liegt zu diesem 
Zeitpunkt R/W auf Low, dann weiß das Display, daß ein Schreibzugriff 
erfolgt, und bereitet sich darauf vor, mit der High-Low Flanke von 
ENABLE die Daten vom Datenbus ( DB0..DB7 ) einzulesen. Dazu muß das 
Display aber noch wissen, wohin diese Daten geschrieben werden sollen. 
Liegt RS auf low, so werden die Daten als Kommando verstanden, und in 
ein Steuerregister geschrieben. Liegt aber RS auf High, so handelt es 
sich um Daten, die angezeigt werden sollen, und in den Textpuffer 
(DDRAM) zu schreiben sind. (oder um die Definition eines neuen Zeichens)



Ist also das, was auf Sprut.de steht, falsch?!?!
Denn dort steht ja drin, das man erst RS und RW mit positiver flanke 
lesen soll.
Bei der negativen werden dann die die daten vom datenbus gelesen.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was soll das bedeuten?

Du setzt erst e=1 und änderst dann die Bits und setzt e=0. Erst e=0,
dann die Bits setzen und dann erst e=1;

Das widerspricht sich doch.

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
>Wie schon 10mal erwähnt in dem Thread erwähnt, der Display Controller
>übernimmt immer von low nach high die Daten.
Das ist ein ganz schlimmer Irrtum. Mit HL werden die Daten übernommen, 
jedenfalls bei HD44780 & Co. E kann übrigens immer auf H stehen, nur zur 
Datenübernahme muss es mal auf L.

Viel Erfolg, Uwe

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LOL



Also kann mir nunmal jemand die korrekte Reihenfolge geben?

Ist es richtig, dass ich zumindest fürs schreiben in den steuerregister:

E=0;
RS=0;
RW=0;
E=1;
DB7..
DB6..
DB5..
DB4..
E=0;

schreiben muss?
Ist das so vom ablauf her korrekt?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich setze zuerst, während E noch auf L ist, RS und die Daten (RW 
ist fest auf L, da ich kein Busy-Flag abfrage), dann warte ich einige 
Takte, dann setze ich E auf H, warte wieder einige Takte und setze 
danach E wieder auf L. Und das funktioniert.

...

Autor: Jochen S. (schiffner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Oliver
nein das ist noch nicht richtig so.

Du stellt zuerst die Daten richtig ein (E steht auf E=0):

RS..
RW..
DB7..
DB6..
DB5..
DB4..

dann sagst du dem Displaycontroller, dass die Zustände jetzt da sind und 
er sie einlesen/bearbeiten kann:

E=1;
kurz warten
E=0;
(erst durch das setzen und rücksetzen von E liest der Displaycontroller 
die Daten die auf RS,RW,DB7 usw. sind)

dann wartest du deine Vorgeschriebene Zeit ab. Jetzt kannst du 
Datenleitungen auf den nächsten gewüschten Zustände setzen:

RS..
RW..
DB7..
DB6..
DB5..
DB4..

jetzt musst du dem Controller wieder sagen das die Daten fertig sind und 
er sie einlesen kann:

E=1;
kurz warten
E=0;

so geht das jetzt jedesmal weiter (das siehst du auch im tut., da kommt 
nach jeder Befehlseingabe [lcd_enable(); und _delay_ms(5);])

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok Dankeschön.

Ich probier es nachher aus.

Aber was mich wundert ist, dass es in dem Tutorial von sprut.de, welches 
ja auch hier auf der seite verlinkt ist, etwas anders steht!
....

Egal.
Ich probiers nachher aus.
Danke nochmal.

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm funktioniert immer noch nicht...
auch nicht mit timer.
Die Zeiten sind dabei schon ziehmlic lang eingestellt...

Autor: Murmel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht hilft dir das ja weiter, ist allerdings für einen Mega8
.equ  F_CPU,  3686400
.include  "AVR.H"
;---------------------------------------------------------------------------
; Reset- und Interruptvektoren          ; VNr.  Beschreibung
  rjmp  main  ; 1     POWER ON RESET
  reti    ; 2     Int0-Interrupt
  reti    ; 3     Int1-Interrupt
  reti    ; 4     TC2 Compare Match
  reti    ; 5     TC2 Overflow
  reti    ; 6     TC1 Capture
  reti    ; 7     TC1 Compare Match A
  reti    ; 8     TC1 Compare Match B
  reti    ; 9     TC1 Overflow
  reti    ; 10    TC0 Overflow
  reti    ; 11    SPI, STC Serial Transfer Complete
  reti    ; 12    UART Rx Complete
  reti    ; 13    UART Data Register Empty
  reti    ; 14    UART Tx complete
  reti    ; 15    ADC Conversion Complete
  reti    ; 16    EEPROM Ready
  reti    ; 17    Analog Comperator
  reti    ; 18    TWI (I²C) Serial Interface
  reti    ; 19    Store Program Memory Ready
;---------------------------------------------------------------------------
; Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  SPL,r16  ; Init Stackpointer LO
  ldi  r16,hi8(RAMEND)
  out  SPH,r16  ; Init Stackpointer HI
  rcall  LCD_init
  rcall  LCD_clear
;---------------------------------------------------------------------------
mainloop:  rcall  wait
  ldi  r16,'H'
  rcall  LCD_data
  ldi  r16,'a'
  rcall  LCD_data
  ldi  r16,'l'
  rcall  LCD_data
  ldi  r16,'l'
  rcall  LCD_data
  ldi  r16,'o'
  rcall  LCD_data
  ldi  r16,' '
  rcall  LCD_data

  rcall  LCD_line2

  ldi  r16,'W'
  rcall  LCD_data
  ldi  r16,'e'
  rcall  LCD_data
  ldi  r16,'l'
  rcall  LCD_data
  ldi  r16,'t'
  rcall  LCD_data
  ldi  r16,' '
  rcall  LCD_data

  rcall  LCD_home

  rjmp  mainloop
;===========================================================================
; hier Unterprogramme und Interruptroutinen zufügen
;---------------------------------------------------------------------------
wait:  push  r24
  ldi  r24,0x13  ; hier delay einstellen 13 = ca. 20yS
w1:  subi  r24,0x01
  rcall  wait20ms
  brcc  w1
  pop  r24
  ret
;---------------------------------------------------------------------------
wait5ms:  ldi  r16,255
  ldi  r17,26
w5ms:  dec  r16
  brne  w5ms
  dec  r17
  brne  w5ms
  ret
;---------------------------------------------------------------------------
wait20ms:  ldi  r16,255
  ldi  r17,104
w20ms:  dec  r16
  brne  w20ms
  dec  r17
  brne  w20ms
  ret
;---------------------------------------------------------------------------
LCD_init:     sbi  DDRD,2          ; LCD RS = OUT
    sbi  DDRD,3          ; LCD E  = OUT
    sbi  DDRD,4        ; LCD D4 = OUT
    sbi  DDRD,5        ; LCD D5 = OUT
    sbi  DDRD,6         ; LCD D6 = OUT
    sbi  DDRD,7         ; LCD D7 = OUT
    cbi  PORTD,2          ; LDC RS = Low

    ; warte bis PowerUp
    ldi  r18,20
powerup:  rcall   wait5ms
    dec  r18
    brne  powerup          ; Power-Up Wartezyklus min 30 ms

    ; sende Resetsequenz kompatibel zu HD44780 Industriestandard
    ldi  r16,0b00110000      ; Reset-Sequenz Teil 1
    out  PORTD,r16
    rcall  LCD_enable      ; Enable-Impuls
    rcall  wait5ms
    ldi  r16,0b00110000      ; Reset-Sequenz Teil 2
    out  PORTD,r16
    rcall  LCD_enable      ; Enable-Impuls
    rcall  wait5ms
    ldi  r18,100        ; Wartezyklus bei RESET LCD min 100 µs
resetLCD:  
    nop
    nop  
    nop
    dec  r18
    brne  resetLCD
    ldi  r16,0b00110000      ; Reset-Sequenz Teil 3
    out  PORTD,r16
    rcall  LCD_enable      ; Enable-Impuls
    rcall  wait5ms

                ; sende init 1
    ldi  r16, 0b00100000        ; 4 Bit Modus aktivieren
    out  PORTD, r16
    rcall   LCD_enable       ; Enable-Impuls
    rcall   wait5ms
    ldi  r16, 0b00101000
    rcall   LCD_cmd             ; Function Set 4 Bit, 2 Zeilen, 5x7
    rcall   LCD_off
    rcall   LCD_clear
    ldi  r16, 0x06
    rcall   LCD_cmd        ; Entry Mode Set, increase+shifted
    rcall   LCD_on
    ret
;---------------------------------------------------------------------------
LCD_data:  ldi  r18,0b0000100  ; RS = hi
  rjmp  LCD_out
;---------------------------------------------------------------------------
LCD_cmd:  ldi  r18,0b0000000  ; RS = lo
LCD_out:  mov  r17,r16
  swap  r17
  andi  r16,0b11110000
  or  r16,r18
  andi  r17,0b11110000
  or  r17,r18
  out  PORTD,r16
  rcall  LCD_enable
  out  PORTD,r17
  rcall  LCD_enable
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_enable:  sbi  PORTD,3  ; Enable high
  nop    ; kurz warten
  nop
  nop
  cbi  PORTD,3  ; Enable wieder low
  ret
;---------------------------------------------------------------------------
LCD_clear:  ldi  r16,0b00000001  ; Display löschen
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_off:  ldi  r16,0b00001000
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_on:  ldi  r16,0x0E
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_home:  ldi  r16,0b00000010  ; Display Cursor HOME
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_line1:  ldi  r16,0b10000000  ; DRAM auf Adresse 0x00
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
LCD_line2:  ldi  r16,0b11000000  ; DRAM auf Adresse 0x40
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------
; Goto r16 = Adresse (Zeile 1 = 0x00..0x0F, Zeile 2 = 0x40..0x4F)
LCD_goto:  ori  r16,0b10000000  ; Goto DRAM auf Adresse r16
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;---------------------------------------------------------------------------

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleiner Tipp: Mach den Takt des Controllers mal gaaanz lahm (100Hz z.B.) 
und häng an jede Daten- und Steuerleitung eine LED. Dann siehst du, was 
sich wirklich tut und was eben nicht. Sofern dein Controller mit einem 
solchen Takt noch läuft natürlich. Kannst auch einen Taster an den 
Takteingang hängen, dann hast du sowas wie Einzelschrittmodus. Nur 
sollte der dann nicht zu stark prellen.
Oder hast du sowas wie einen Logic Analyser?

Autor: Oliver D. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah jo, da sieht man ebenfalls, wie erst die daten bei EN= Low 
geschrieben werden. Dann kurz mit enable fuktion einmal an und 
ausgeschatet wird...


Ich werde es nun erstmal ordentlich mit timerfunktion etc. 
programmieren, bevor ich hier weitere Fragen stelle ;)

Autor: Murmel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne deine Verdrahtung ja nicht, aber ich würde die nicht genutzen 
Signaleingänge des Displays alle auf GND legen. Nur um keine Zicken rein 
zubekommen.

Autor: Jochen S. (schiffner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver D. wrote:
> So, ich habe hier mal was mit timer programmiert.
>
> Ich habe mich dabei zu 100% an die anleitung von sprut.de gehalten.
> Es müsste so funktionieren, tut es aber nicht.
> Timing ist auch genug drinne!

nochmal was zu deinem Code vom 09.11.2007 17:41 :

  void display_init (void)
  {
  unsigned int timerstate;
  LED=0xFF;

  if(TF0==1) // Bei einem Z�hler�berlauf wird timerstate inkrementiert
  {
  timerstate++;
  }
  //mindestens 15ms warten, getan durch timestate >= 20

  if(timerstate>=20 && timerstate <= 23)

  {
  EN=0;//Low setzen
  LED=0;
  }usw.

das is ja schön und gut mit deinem timer, aaaber
da solltest du mal mindestens eine while-Schleife oder so drum setzen, 
sonst rennt dein Programm genau einmal komplett durch "display_init" 
ohne irgend eine if Bedingung zu erfüllen und springt wieder zurück zu 
main und nichts passiert.
nur mal so nebenbei :-)

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

oben siehst du, dass die funktion display init heisst.
Sie wird einmal in meinem hauptprogramm ausgeführt.

Danach kommt for schleife mit (;;)

Das problem kann ich also ausschliessen.


Der Tipp mit den LEDs und takt ist ne gute geschichte...

Leider habe ich nur ein 11,0592mhz quarz und sonst nix :(

Ich werde heute mal alles ordentlich programmieren und dann nochmal 
reinstellen!

Autor: Oliver D. (highspeed-oliver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achja, ist es zwingend erforderlich oder überhaupt machbar, die ports 
des Displays bei nichtverwenden auf GND zu legen?
Ich arbeite ja nur im 4 bit modus und viele pins sind unbenutzt...

Sollte man dann alles auf GND legen oder eher nicht?

Autor: Oliver D. (highspeed-oliver)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
WUUUUHUUUUUUUUU

JABBA DABBA DOOOO

ES KLAPPT!!!!


Ich habe endlich alles ordentlich programmiert und ich sehe wie das 
display in den 2 zeilen modus wechsel!!!


Oh man geil. Das ist echt toll als Anfänger sowas hinzubekommen und 
bestärkt einen, einen weiteren nachmittag dran zu arbeiten.

Ich poste einfach mal den source code...
Vielleicht gibts ja noch jemanden der dasselbe am at89s52 machen will.

Danke nochmal an alle, die an mich geglaubt haben ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.