Forum: Mikrocontroller und Digitale Elektronik LCD Busy Flag Abfrage im 8 Bit Modus - die zweite


von Rudolf M. (rudolf_58)


Angehängte Dateien:

Lesenswert?

Ich muss nochmals um Hilfe bitten. Nach Einarbeitung der 
Änderungsvorschläge läuft das Proagramm noch immer nicht so wie es soll.
Das Szenario zur Erinnerung: Ein ATMega8A steuert ein HD44780 LCD an. 
Solange ich mit delays arbeite kommt das heraus wie es sein soll. Sobald 
ich über die Busy Flag Subroutine fahre, kommen nur Fragmente an. Ich 
finde den Fehler einfach nicht. Ich ersuche um Hilfe. Im Anhang die 
komplette *.asm  Source. Ich hoffe dass das file diesmal brauchbar zu 
lesen ist. Falls nicht, dann ersuche ich auch dazu um Hilfe. Ich arbeite 
mit dem Studio 7 und hänge die main.asm an. Vielen Dank !

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> Ich muss nochmals um Hilfe bitten.

Du musst ENABLE auf 1 setzen, dann den Datenport lesen
und dann erst ENABLE wieder 0 setzen. Das ENABLE aktiviert
beim Lesen die Bustreiber des LCD, danach sind sie wieder
inaktiv.

So wie du es jetzt machst liest du mit deinem Aufruf der
ENABLE-Routine immer ins Leere.

von Mitlesa (Gast)


Lesenswert?

Mitlesa schrieb:
> So wie du es jetzt machst liest du mit deinem Aufruf der
> ENABLE-Routine immer ins Leere.

Hab mich geirrt.

Aber hier:

sbrc temp1, PIN_BF      ; Schleife verlassen wenn BF = 0 ist

hast du BF mit 7 definiert, das Busy Flag ist jedoch auf Bit 7,
und dieser Wert ist als Bit-Maske oder Wert 0x80 und nicht 7.

von Rudolf M. (rudolf_58)


Lesenswert?

Mitlesa schrieb:
> Du musst ENABLE auf 1 setzen, dann den Datenport lesen
> und dann erst ENABLE wieder 0 setzen.

Hm, genau das mache ich ja (denke ich zumindest):
sbi Steuerport, PIN_E
nop
in temp1, Datenport
cbi Steuerport, PIN_E

oder verstehe ich das falsch ?

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> oder verstehe ich das falsch ?

Ich habe nachgebessert.

von Rudolf M. (rudolf_58)


Lesenswert?

Mitlesa schrieb:
> hast du BF mit 7 definiert, das Busy Flag ist jedoch auf Bit 7,
> und dieser Wert ist als Bit-Maske oder Wert 0x80 und nicht 7.

Verstehe ich das richtig ?
temp1 = 0b10000000 = 0x80
Super, werde ich probieren. Ich dachte dass ich hier die Bitnummer 
eingeben muss. Das Problem liegt wieder mal zwischen meinen Ohren. Wenn 
ich das Instruction Set zu Rate ziehe sehe ich da eine Bitnummer aber 
keine Anwendung einer Bitmaske. Vielen Dank!

von Rudolf M. (rudolf_58)


Lesenswert?

Rudolf M. schrieb:
> Wenn
> ich das Instruction Set zu Rate ziehe sehe ich da eine Bitnummer aber
> keine Anwendung einer Bitmaske.

Aus dem Instruction Set:
sbrc r0,7 ; Skip if bit 7 in r0 cleared

danach müsste die Anweisung eigentlich so passen wie sie ist.
Übersehe ich dabei etwas ?

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> Übersehe ich dabei etwas ?

Ok dann habe ich möglicherweise den Opcode falsch verstanden,
bin in Assembler nicht so fit.

In C ist das alles ganz einfach .....

von Matthias L. (Gast)


Lesenswert?

1
LcdBusyWait:              
2
    sbi Steuerport, PIN_E    ; Enable hochsetzen      
3
    nop
4
    in temp1, Datenport
5
    cbi Steuerport, PIN_E
6
    sbrc temp1, PIN_BF      ; Schleife verlassen wenn BF = 0 ist      
7
  rjmp LcdBusyWait


Hm..

müsste das hier:
1
    in temp1, Datenport

nicht eher so lauten:
1
    in temp1, Busyflag  // read PIND not PORTD

von John Doe (Gast)


Lesenswert?

Mitlesa schrieb:
> Rudolf M. schrieb:
>> Übersehe ich dabei etwas ?
>
> Ok dann habe ich möglicherweise den Opcode falsch verstanden,
> bin in Assembler nicht so fit.
>
> In C ist das alles ganz einfach .....

https://www.youtube.com/watch?v=0iBUFi9s1LM

von Rudolf M. (rudolf_58)


Lesenswert?

Matthias L. schrieb:
> in temp1, Busyflag  // read PIND not PORTD

Mit " in temp1 " wird der gesamte Datenport eingelesen.
Im MSB ist dann das BF zu finden, das dann in der Folge ausgewertet 
wird.
"Busyflag" = 7, das funktioniert so nicht denke ich

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> Mit " in temp1 " wird der gesamte Datenport eingelesen.

Da hat Mathias aber Recht, denn die Register-Adresse eines
Ports ist lesend und schreibend verschieden, daher gibt
es in den Defines PORTx und PINx.

von Rudolf M. (rudolf_58)


Lesenswert?

Mitlesa schrieb:
> Rudolf M. schrieb:
>> Mit " in temp1 " wird der gesamte Datenport eingelesen.
>
> Da hat Mathias aber Recht, denn die Register-Adresse eines
> Ports ist lesend und schreibend verschieden, daher gibt
> es in den Defines PORTx und PINx.

Richtig, da hab ich mich jetzt selber an der Nase zu nehmen.
Vielen Dank, das sollte nun wirklich funktionieren !!

von Rudolf M. (rudolf_58)


Lesenswert?

Rudolf M. schrieb:
> Vielen Dank, das sollte nun wirklich funktionieren !!

Es ist wie verhext, auch die Beseitigung von diesem kapitalen Fehler 
bringt keine Änderung. Es funktioniert noch immer nicht. :-(

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> Es ist wie verhext,

Welche Taktfrequenz hat dein Controller? Könnte es sein dass er
mit einem NOP alleine zu schnell ist das Datenregister zu lesen,
das LCD seine Daten (BUSY Flag) noch gar nicht bereit hat? Schau
in das Datenblatt deines LCDs, wie lange braucht es bis die
Daten nach dem ENABLE bereit sind? Die LCDs sind bekannter-
massen recht langsam.

von Mitlesa (Gast)


Lesenswert?

Rudolf M. schrieb:
> Es ist wie verhext,

Ich habe mal in meinen alten C-Sourcen nachgeschaut, bei Rück-
lesen des Busy-Flags habe ich dort immer ein Delay von 2usec
drin bevor ich den Port lese, sonst hatte es höchst-
wahrscheinlich bei meinen LCDs nicht funktioniert ....

Leider ist es bei diesen LCDs mehr oder weniger sinnlos den
I/O auf Geschwindigkeit zu trimmen da auch mit simplen
Delays in der Write Routine immer noch genug Zeit bleibt das
Display wesentlich schneller zu betreiben als man es lesen
kann. Ich weiss schon ....

von Rudolf M. (rudolf_58)


Lesenswert?

Mitlesa schrieb:
> Leider ist es bei diesen LCDs mehr oder weniger sinnlos den
> I/O auf Geschwindigkeit zu trimmen da auch mit simplen
> Delays in der Write Routine immer noch genug Zeit bleibt das
> Display wesentlich schneller zu betreiben als man es lesen
> kann.

Völlig richtig. Mir geht es ja nicht darum etwas möglichst schnell zu 
betreiben, sondern zu verstehen warum das nicht funktioniert. Natürlich 
habe ich das Datenblatt schon zur Hand genommen und offensichtlich dabei 
etwas nicht richtig verstanden. Ich werde das nochmals checken. Für 
heute ist Schluss bei mir. Morgen werde ich mich wieder darüberbeugen 
und berichten.
Vielen Dank vorerst !

von Mitlesa (Gast)


Angehängte Dateien:

Lesenswert?

Rudolf M. schrieb:
> Mir geht es ja nicht darum etwas möglichst schnell zu
> betreiben, sondern zu verstehen warum das nicht funktioniert.

Ja, das ist ja auch ganz vernünftig und richtig, deshalb bleibe
ich auch noch dabei ....

Rudolf M. schrieb:
> und offensichtlich dabei etwas nicht richtig verstanden.

Fürs Lesen gilt:

Das Timing des "Standard-Controllers" zeigt dass man R/W und
RS setzen sollte bevor man nach einer Wartezeit von t_as die
Enable Leitung aktiviert. Dann jedoch ist noch eine Zeit t_ddr
zu warten bis der Display-Controler gültige Daten ausgegeben
hat. Das ist eine Menge Zeit in der dein AVR-Controller schon
einige Opcodes abarbeiten kann, also schneller ist als man
vielleicht vermutet. Die minimale Enable Pulsbreite ist bei
schnellen Mikrocontrollern auch sehr leicht unterschreitbar.

Auch die Gesamt-Zykluszeit darf nicht zu kurz sein, da ist man
mit schnellem Assembler Code schnell auf der unsicheren Seite.

von spess53 (Gast)


Lesenswert?

HI

Bei mir funktioniert das hier:
;----------------------------------------------------------------------- 
-------
;           Abfrage BUSY-Flag(D7)
;           changed: -
;

                      .if use_isbusy

isbusy:     push r16
            clr r16
            out lcdir,r16              ;LC-Port input
            ser r16
            out lcdat,r16              ;pullup
            cbi lcctl,lc_rs            ;Daten lesen
            sbi lcctl,lc_rw            ;Read
            sbi lcctl,lc_e             ;Enable
            nop
            nop                        ;warten
ib1:        in r16,lcpin               ;read
            andi r16,$80               ;BIT7=0
            brne ib1                   ;wenn nicht zurück
            cbi lcctl,lc_e             ;Disable Anzeige
            pop r16
            ret

                      .endif

;----------------------------------------------------------------------- 
-------

MfG Spess

von Ozvald K. (Gast)


Lesenswert?

Hallo,

jetzt ohne mich in Dein Sourcecode hinein zu arbeiten frage dich ob du 
ein sauberes Umschalten zwischen Ein-/Ausgang auch berücksichtigt hast:

"When switching between tri-state ({DDxn, PORTxn} = 0b00) and output 
high ({DDxn, PORTxn} = 0b11), an intermediate state with either pull-up 
enabled ({DDxn, PORTxn} = 0b01) or output low ({DDxn, PORTxn} = 0b10) 
must occur. Normally, the pull-up enabled state is fully acceptable, as 
a high-impedant environment will not notice the difference between a 
strong high driver
and a pull-up. If this is not the case, the PUD bit in the SFIOR 
Register can be set to disable all pull-ups in all ports.
Switching between input with pull-up and output low generates the same 
problem. The user must use either the tri-state ({DDxn, PORTxn} = 0b00) 
or the output high state ({DDxn, PORTxn} = 0b11) as an intermediate 
step."

von Mitlesa (Gast)


Lesenswert?

spess53 schrieb:
> Bei mir funktioniert das hier:

.... abhängig von der Taktfrequenz des Controllers (?)

[ ] ja
[ ] nein

Wenn das LCD noch keine Daten liefert weil die Setup-Wartezeit
noch nicht abgelaufen ist kann der (vermutlich) floatende Bus
beliebig Einsen oder Nullen hergeben je nach physikalischer
Ausstattung und Daten-Vorgeschichte. Ein Busy-Handshake kann
also auch (so halbherzig) funktionieren wenn das Daten-Setup-
Timing verletzt wird.

von Rudolf M. (rudolf_58)


Lesenswert?

Mitlesa schrieb:
> Das Timing des "Standard-Controllers" zeigt dass man R/W und
> RS setzen sollte bevor man nach einer Wartezeit von t_as die
> Enable Leitung aktiviert. Dann jedoch ist noch eine Zeit t_ddr
> zu warten bis der Display-Controler gültige Daten ausgegeben
> hat.

Vielen Dank für die tolle Dokumentation. Im timing chart ist t_as mit 
min. 140ns angegeben. Wenn die CPU mit 1 Mhz betrieben wird ist das 1 
Mikrosek pro Takt. Das wäre also mit einem NOP mehr als ausreichend. Was 
die t_ddr Zeit betrifft habe ich folgendes im Datenblatt: im Lesemodus 
(LCD -> CPU) ist keine Zeit angegeben. Dafür ist im Schreibmodus eine 
max. Zeit von 320ns
angegeben.
Zu Ihrer vorangehenden Frage bez. Geschwindigkeit:
Ich versuche immer zwei Geschwindigkeiten mit mit dem int. Osc.: Einmal 
1 MHz und dann 8 MHz.
Solange ich mit dem delay arbeite arbeitet das Programm wie es soll. 
Sowohl im 1 MHz wie auch im 8 MHz Betrieb.
Im BF Betrieb mit 1 MHz wird alles auf dem Display ausgegeben wie es 
sein soll, nur der Cursor befindet sich auf der "falschen" Stelle
, nämlich in der zweiten Zeile Pos 5.
Im ( MHz Betrieb wird nur mehr der der erste Buchstabe richtig angezeigt 
und der Rest nicht, der Cursor steht wieder auf der selben "falschen" 
Stelle.

von Rudolf M. (rudolf_58)


Lesenswert?

Ozvald K. schrieb:
> Normally, the pull-up enabled state is fully acceptable, as
> a high-impedant environment will not notice the difference between a
> strong high driver
> and a pull-up. If this is not the case, the PUD bit in the SFIOR
> Register can be set to disable all pull-ups in all ports.

Toller Hinweis, danke. Ich habe in der Hardware 4,7k fix verdrahtet als 
pull up's verbaut. Das hab ich so in einem Beitrag im Netz gefunden und 
auch im Datenblatt finde ich den Hinweis auf Pull Ups falls es Probleme 
geben sollte. Die habe ich quasi vorsichtshalber verbaut. Im übrigen 
habe ich die Hardware 2 mal gebaut um bei der Fehlersuche zumindest 
hardwareseitig die Fehlerquelle zu minimieren. Zuletzt muss ich 
gestehen, dass die BF Abfrage schon völlig problemlos gelaufen ist, ich 
aber das file irrtümlich überschrieben habe. Nein, auf die Frage nach 
einer Datensicherung antworte ich nicht :-)

von Rudolf M. (rudolf_58)


Lesenswert?

spess53 schrieb:
> n r16,lcpin               ;read
>             andi r16,$80               ;BIT7=0
>             brne ib1                   ;wenn nicht zurück

Danke für den Tip, ich hab den Code angepasst übernommen. Ist leider das 
gleiche Fehlerbild wie vorher.

von Rudolf M. (rudolf_58)


Lesenswert?

spess53 schrieb:
> .if use_isbusy

Eine Zusatzfrage: die IF Anweisung finde ich in Assembler bei Microchip 
nicht (Instruction Set). Wo ist diese zu finden ?

von Hugo H. (hugohurtig1)


Lesenswert?

Rudolf M. schrieb:
> Eine Zusatzfrage: die IF Anweisung finde ich in Assembler bei Microchip
> nicht (Instruction Set). Wo ist diese zu finden

http://application-notes.digchip.com/015/15-16013.pdf

von Hugo H. (hugohurtig1)


Lesenswert?

Rudolf M. schrieb:
> Danke für den Tip, ich hab den Code angepasst übernommen. Ist leider das
> gleiche Fehlerbild wie vorher.

Warum versuchst Du Dich eigentlich in / mit Assembler, wenn Du keine 
Ahnung davon hast? Sagt Dir der Begriff "Labels" etwas?

Schau Dir doch einfach mal BASCOM an - ist viel einfacher und wird gut 
unterstützt. C oder C++ oder ... sind (vielleicht) auch einfacher zu 
erlern, wie Assembler.

Wenn Du unbedingt mit Assembler "spielen" willst musst Du Dich schon 
intensiv damit auseinandersetzen (das gilt eigentlich für alle 
Programmiersprachen).

Einfach nur etwas abschreiben / kopieren ist selten sinnvoll nutzbar.

von Teo D. (teoderix)


Lesenswert?

Rudolf M. schrieb:
> Ich habe in der Hardware 4,7k fix verdrahtet als
> pull up's verbaut.

Der HD44780 kann NUR 250µA treiben! Das wären an 5V, 20k! Typisch 
wären dann also 50k als Pull-Up....

von Hugo H. (hugohurtig1)


Lesenswert?

Wie wäre es denn, wenn Du das mal durchspielst

https://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD

und danach Fragen stellst.

von Rudolf M. (rudolf_58)


Lesenswert?

Teo D. schrieb:
> Der HD44780 kann NUR 250µA treiben! Das wären an 5V, 20k!

Danke, nun in der nächsten Auflage des HW Designs werde ich das 
berücksichtigen. Demnach müsste mein LCD im Dauerstress sein ...
Trotzdem funktioniert das Teil im delay Betrieb so wie es soll.
Aus diesem Grund glaube ich nicht dass das die Ursache für das Problem 
ist.
Zumal die 4,7k an + hängen, somit ist das LCD eher ein "getriebener" als 
ein "treibender" . Wen ich damit nun völlig falsch liege bitte ich um 
Aufklärung. Noch ein Hinweis: wenn ich mir die Signale am Oszi ansehe, 
dann sehen die Signale bezüglich Steilheit der Flanken und Form im 
Allgemeinen recht vernünftig aus.

von spess53 (Gast)


Lesenswert?

Hi

>spess53 schrieb:
>> .if use_isbusy

>Eine Zusatzfrage: die IF Anweisung finde ich in Assembler bei Microchip
>nicht (Instruction Set). Wo ist diese zu finden ?


Das gehört zu den Assembler directives des Assembler2 vom AVR Studio4:

IF,IFDEF,IFNDEF -  conditional assembly
Conditional assembly includes a set of commands at assembly time. The 
IFDEF directive will include code till the corresponding ELSE directive 
if <symbol> is defined.  The symbol must be defined with the EQU or SET 
directive. (Will not work with the DEF directive)  The IF directive will 
include code if <expression> is evaluated different from 0. Valid till 
the corresponding ELSE or ENDIF directive.

Up to 5 levels of nesting is possible.

Syntax:
.IFDEF <symbol>
.IFNDEF <symbol>
.IF <expression>

.IFDEF <symbol> |.IFNDEF <symbol>
...
.ELSE | .ELIF<expression>
...

Ich benutze das um Teile des Codes von der Assemblierung auszuschließen:

;##############################################################
;# 
#
;#                              Aktivierungen 
#
;# 
#
;##############################################################

                      .equ use_lcd_init    = 0
                      .equ use_home_curs   = 0
                      .equ use_sec_line    = 0
                      .equ use_clear_disp  = 0
                      .equ use_isbusy      = 0
                      .equ use_wrcmd       = 0
...

MfG Spess

von Teo D. (teoderix)


Lesenswert?

Rudolf M. schrieb:
> Trotzdem funktioniert das Teil im delay Betrieb so wie es soll.

3.. 2.. 1.. hastes?! ;P
Delay Betrieb! -> Ausgangstreiber sind in Rente geschickt!

von Rudolf M. (rudolf_58)


Lesenswert?

Teo D. schrieb:
> 3.. 2.. 1.. hastes?! ;P
> Delay Betrieb! -> Ausgangstreiber sind in Rente geschickt!

Verstehen tu ich das jetzt nicht wirklich, aber ich glaube zu wissen was 
Sie damit meinen :-)
Ich werde die Pull ups entfernen .... und dann wahlweise die internen 
pull up's aktivieren.
Was mir jetzt durch den Kopf geht: Warum hat das dann schon mal perfekt 
mit der BF Abfrage funktioniert. Das war die gleiche Hardware ....

Leider werden ich bis Ende der Woche nicht mehr Zeit haben mich damit zu 
beschäftigen. Sobald ich wieder Zeit dafür habe werde ich mich mit dem 
Ergebnis zurückmelden.

Vielen Dank an Alle ! Die Fülle der kompetenten Hinweise und Tips hat 
mich wirklich beeindruckt.

von Rudolf M. (rudolf_58)


Lesenswert?

spess53 schrieb:
> Das gehört zu den Assembler directives des Assembler2 vom AVR Studio4:

Klasse ! Danke !

von Teo D. (teoderix)


Lesenswert?

Rudolf M. schrieb:
> Verstehen tu ich das jetzt nicht wirklich, aber ich glaube zu wissen was
> Sie damit meinen :-)

Egal, hab mich vertan. Die 250mA(max) liefern die internen PullUps.

Rudolf M. schrieb:
> Was mir jetzt durch den Kopf geht: Warum hat das dann schon mal perfekt
> mit der BF Abfrage funktioniert. Das war die gleiche Hardware ....

Kein wunder, die Eingänge können gegen GND ja auch 1,2mA ziehen... :/

Sorry für die sinnlose Aufregung. :(

von spess53 (Gast)


Lesenswert?

Hi

>Ich werde die Pull ups entfernen .... und dann wahlweise die internen
>pull up's aktivieren.

Die Ausgänge des HD44780 haben, außer PIN E, interne PullUps. Externe 
PullUps, auch die des Controllers sind absolut unnötig.

MfG Spess

von Ozvald K. (Gast)


Lesenswert?

Habe irgendwann mit ATMEGA8 "herumgespielt", bei mir ist mit 1MHz 
gelaufen, LCD mit 4-Bit Interface angesprochen (PortD4-7), keine 
externen Pullups verwendet. Hier der Teil meines Programms wo ich das 
Busy-Flag abgefragt habe. Vielleicht hilft dir das:

.equ E = 0    ;Enable control bit LCD
.equ RW = 2    ;Read/Write control bit LCD
.equ RS = 3    ;Register select control bit LCD
.
.
.
.
BUSYREAD:  sbi PORTD,PORTD7  ;set D7 high. With DDD7=0 is acting
                                        ;as input with activated pullup.
    cbi DDRD, DDD7    ;set direction for D7 as input.
    cbi PORTD, RS
    sbi PORTD, RW
br1:    sbi PORTB, E
    nop
    in R16,PIND    ;load the upper 4 bits
    cbi PORTB, E
    nop
    sbi PORTB, E
    nop      ;no need to load the lower 4 bits
    cbi PORTB, E
    bst R16,7    ;load bit7 into T flag
    brts br1    ;wait until Busy flag is high
    sbi DDRD, DDD7    ;set D7 to output
                ret

von Matthias L. (Gast)


Lesenswert?

>Solange ich mit dem delay arbeite arbeitet das Programm wie es soll.
>Sowohl im 1 MHz wie auch im 8 MHz Betrieb.

Was ich eigentlich schreiben wollte, als mir das mit dem PIND/PORTD 
aufgefallen ist:

Ich vermute, es ist ein Timingproblem. Ich würde etwas zyklisches 
testen. zB alle 100ms wird ein LCD-Zugriff mit Delay durchgeführt (das 
geht ja laut TO) und danach noch einer per BusyFlag-Abfrage. Dann würde 
ich mir das ansehen.

Ich vermute, das nach dem Ansteuern des Displays das Busyflag noch nicht 
gesetzt ist, aber der µC das bereits als nicht-mehr-gesetztes Flag 
auswertet und weiterläuft...

von Jörn P. (jonnyp)


Lesenswert?

Hab keinen Bock drau deinen code auseinander zu nehmen.
Es folgt hier nur allgemeines.
Gegenüber einem mC ist ein LCD ein Lahmarsch. Das Timing des LCD muss 
sehr genau eingehalten werden. Langsamer schadet nicht, schneller schon.
Zwischen den LCD Controllern gibt es timing Unterschiede. Meine 
Initialisierung geht vom langsamsten chip aus. Deshalb verwende ich das 
busy flag, damit ich im Betrieb "volle Kanne LCD" fahren kann. Verwende 
nobs zwischen den einzelnen Befehlen, die kannst du später Häppchenweise 
wieder raus nehmen und testen ob es immer noch funzt.
1. R/W lo schalten, dadurch geht das LCD auf Input.
2. den µC-Port auf Input schalten
3. nops
4. R/W auf hi legen, damit wird LCD auf Output gesetzt
5. nops
6. E (nable)auf hi legen
7. nops
8. lesen datenbyte (pin-x) und checken von bit 7 (busy flag)
9. Falls busy zurück zu 8.
10. Wenn nicht mehr busy:
11. E auf lo
12. R/W auf lo (jetzt sind beide ports µC und LCD auf Input.
Das ist sehr wichtig, denn sonst kann es gewaltig knirschen.

Dann kann der µC port als Ausgang für das nächste Byte zum LCD 
geschaltet werden.
Das ist ein ziemlicher Aufriss, hat sich imho aber gelohnt, denn bis 
jetzt laufen bei mir alle LCDs auf Anhieb.

von Teo D. (teoderix)


Lesenswert?

Jörn P. schrieb:
> Hab keinen Bock drau deinen code auseinander zu nehmen.
> Es folgt hier nur allgemeines.

Dann such dir doch ne Krabbelgruppe für Anfänger!

von Rudolf M. (rudolf_58)


Angehängte Dateien:

Lesenswert?

Matthias L. schrieb:
> Ich vermute, das nach dem Ansteuern des Displays das Busyflag noch nicht
> gesetzt ist, aber der µC das bereits als nicht-mehr-gesetztes Flag
> auswertet und weiterläuft...

Sorry für die späte Reaktion, die letzten Tgae waren stressig für mich. 
Ich habe mir nun die Signale nochmals mit dem Oszi angesehen. Dabei 
fällt mir auf, dass mit dem Hochsetzen von Enable innerhalb der Busy 
Schleife das D7 Signal auf Low geht und mit fallender Flanke von E 
wieder hochgesetzt wird. Folgerichtig wird die Schleife sofort wieder 
verlassen, da BF ja Low ist. Jetzt seh ich den Wald vor lauter Bäumen 
nicht mehr ....
Im Anhang ein Bild von den Signalen. Gelb ist immer E und dazu jeweils 
RS RW und D7 gestellt. Geht leider nicht anders mit dem Zweikanal Oszi, 
aber dafür sollte es eigentlich passen und ein großer "paint" Künstler 
bin ich auch nicht :-)

von Pandur S. (jetztnicht)


Lesenswert?

Vergiss das Busy Flag. Weshalb willst du dir das antun ?
Es gibt im Datenblatt zwei Zeiten.
1) Wait nach Power Up, eher lange, in den ms.
2) Wait nach Schreiben, vielleicht 10us.

Ich mach das jeweils mit einer Timer Zustandsmaschine. Also nicht im 
Timer Interrupt, sondern im main.
Jeden Tick wird ein Zeichen geschrieben. So kann ich vielleicht 10 
Updates des Displays pro sekunde machen. Mehr ist eh sinnlos.

von Peter D. (peda)


Lesenswert?

Jörn P. schrieb:
> 6. E (nable)auf hi legen
> 7. nops
> 8. lesen datenbyte (pin-x) und checken von bit 7 (busy flag)
> 9. Falls busy zurück zu 8.

Das widerspricht dem Datenblatt und wird daher nicht mit allen LCDs 
funktionieren, wenn überhaupt.
Die korrekte Methode ist, für jedes Auslesen, das E neu zu pulsen. Also 
genau so, wie es im Datenblatt abgebildet ist.

Und im 4Bit-Mode muß man E immer 2-mal pulsen, da die Nibble im Wechsel 
gelesenen werden (wie auch im Datenblatt abgebildet).

Es ist immer am einfachsten, sich genau nach dem Datenblatt zu richten.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
wie @peda schon sagte: Dabla beachten.
read write nicht vergessen.
Man schaltet damit den Port auf Lesen für das Busybit und zurück.
Für Vierbit:
ein Beispiel im Anhang.
Weil das Busyflag ja nicht im unteren Nibble ist, wird "Dummyausgabe"
gesetzt.

ciao
gustav

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Rudolf M. schrieb:
> Jetzt seh ich den Wald vor lauter Bäumen
> nicht mehr ....

Schick mal vor dem Busy-Test ein Kommando, was richtig lange dauert, 
z.B. Clear Display (1,64ms).

von Ozvald K. (Gast)


Lesenswert?

Aus deinem Sourcecode:

LCD_Busy:

  push temp1
  push temp2

  clr temp1              ; Datenportrichtung auf Low -> Lesen
  out Datenportrichtung, temp1    ; DDRD = 0 = Eingang
  cbi Steuerport, PIN_RS      ; RS auf Low (Command)
  sbi Steuerport, PIN_RW      ; RW auf High Lesen CPU <-- LCD
  rcall Lcd_PulsE

  LcdBusyWait:
    sbi Steuerport, PIN_E    ; Enable hochsetzen
    nop
    in temp1, Datenport
    cbi Steuerport, PIN_E
    sbrc temp1, PIN_BF      ; Schleife verlassen wenn BF = 0 ist
  rjmp LcdBusyWait

  cbi Steuerport, PIN_RW        ; RW auf Low Schreiben CPU --> LCD
  ldi temp1,0xFF
  out Datenportrichtung, temp1      ; Datenportrichtung auf High -> 
Schreiben

  rcall Lcd_PulsE

  pop temp2
  pop temp1
ret

Ist da nicht ein bisschen zu viel Lcd_Pulse?  Bei Wechsel 
Datenportrichtung auf Ausgang wird auf E gepulst. Was ist am Port in 
diesem Augenblick? Du schreibst etwas in LCD. Bei Datenportrichtung auf 
Eingang wird auch gepulst. Wozu?

von Rudolf M. (rudolf_58)


Lesenswert?

Ozvald K. schrieb:
> Ist da nicht ein bisschen zu viel Lcd_Pulse?  Bei Wechsel
> Datenportrichtung auf Ausgang wird auf E gepulst. Was ist am Port in
> diesem Augenblick? Du schreibst etwas in LCD. Bei Datenportrichtung auf
> Eingang wird auch gepulst. Wozu?

Klasse ! Sie haben einen Volltreffer gelandet. Durch den Rauswurf der 
beiden PulsE läuft jetzt alles prima ! Vielen Dank !
Es halt so wie immer: Die Schaltung macht eben genau das was man 
programmiert hat ..... und nicht das was man denkt dass man programmiert 
hat :-)

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.