www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD an ATmega 8 Routine, die das Busy Flag abfragt, läuft nicht!


Autor: Olli R. (downunderthunder42)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe hier den ATmega8 und habe die Subroutinen, die für die 
Ansteuerung des LCD (siehe AVR Tutorial) größtenteils neu 
geschrieben/umgeschrieben, so dass nicht mehr überall "delays" 
zwischengepackt werden müssen, sondern stattdessen das Busy Flag 
abgefragt wird.

Leider funktioniert das ganze nicht.

Der Code wird zwar fehlerfrei assembliert aber es tut sich nichts am 
LCD.

wenn ich die lcdroutines.asm, wie sie im AVR-Tutorial zu finden ist, 
verwende läuft alles, allerdings muss ich dann natürlich den PIN_R/W auf 
GND legen.

somit muss irgendwo ein Logikfehler in meiner geänderten lcdroutines.asm 
sein. (Genauer wohl in der Subroutine "lcd_busy".

Ich habe mal beide Programme angefügt:
LCD.rar enthält eine einfache String-Ausgabe mit der lcdroutines.asm aus 
dem Tutorial (ohne Abfrage des Busy-Flag)

LCD_RW1.rar enthält die Stringausgabe mit meiner umgeschriebenen 
lcdroutines.asm (läuft so leider nicht)

Ich betreibe das LCD an PORTC, und die Umschaltung zwischen 
LCD-lesen/schreiben (PIN_RW) liegt auf PD0 an PORTD

Autor: Edding (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erster befehl:

ldi   temp1, 0<<PC3

Was ist 0, wenn man es um drei Stellen Verschiebt?
.
.
.
Immer noch 0.

Autor: Edding (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und:
das Busy-Bit kannst du erst NACH einem (ganzen!) Befehl abfragen. 
Zwischen den beiden 4Bit-Nibbels geht das nicht.
Und erst recht nicht geht das während der E-Puls gerade läuft. (Der 
E-Puls muss eh nur sehr sehr kurz sein, da waren die NOPs schon richtig)

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Edding schrieb:
> ldi   temp1, 0<<PC3
>
> Was ist 0, wenn man es um drei Stellen Verschiebt?

OK schreibt man dann besser:

cbi LCD_DDR, PC3


und zum Schluss wieder

sbi LCD_DDR,PC3

?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Um das Busy-Flag zu Lesen musst du auch mir E wackeln.
....
wrcmd10:              nop
                      sbi lcctl,lc_e             ; Enable high
                      nop
                      in r16,lcpin               ; Busy Flag
                      nop
                      cbi lcctl,lc_e             ; Enable low
                      nop
                      sbi lcctl,lc_e             ; Enable high
                      nop
                      in r17,lcpin               ; unteres Nibble
                      nop 
                      cbi lcctl,lc_e             ; Enable low

                      swap r16
                      andi r16,0b10000000        ; Busy 0 ?
                      brne wrcmd10
....

MfG Spess

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spess53 schrieb:
> Um das Busy-Flag zu Lesen musst du auch mir E wackeln.

Ich werde das mal gleich testen.
Vielen Dank soweit

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spess53 schrieb:
> ....
> wrcmd10:              nop
>                       sbi lcctl,lc_e             ; Enable high
>                       nop
>                       in r16,lcpin               ; Busy Flag
>                       nop
>                       cbi lcctl,lc_e             ; Enable low
>                       nop
>                       sbi lcctl,lc_e             ; Enable high
>                       nop
>                       in r17,lcpin               ; unteres Nibble
>                       nop
>                       cbi lcctl,lc_e             ; Enable low
>
>                       swap r16
>                       andi r16,0b10000000        ; Busy 0 ?
>                       brne wrcmd10
> ....

ach müsste es nicht heissen:
breq wrcmd10 ; schließlich will aus dieser Subroutine, wenn das BusyFlag 
nicht mehr gesetzt ist . LCD Busy --> Busy Flag =1
LCD_ nicht Busy --> Busy Flag = 0  ?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man gewinnt durch die Busy-Abfrage aber rein garnichts.

Ein Mensch soll das LCD ja auch ablesen können. Daher macht man 
LCD-Ausgaben mit Absicht viel langsamer, als sie (auch mit Waits) 
benötigen.
Die CPU-Last beträgt <1%, somit ist eine Optimierung nur unnötige 
Arbeit.


Peter

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ach müsste es nicht heissen:...

Nein. Wenn Busy 1 ist, dann ist das LCD noch beschäftigt.

>Man gewinnt durch die Busy-Abfrage aber rein garnichts.

Bitte keine Glaubenskriege.

>Ein Mensch soll das LCD ja auch ablesen können. Daher macht man
>LCD-Ausgaben mit Absicht viel langsamer, als sie (auch mit Waits)
>benötigen.

Darum geht es doch gar nicht.

MfG Spess

Autor: Olli R. (downunderthunder42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spess53 schrieb:
>>ach müsste es nicht heissen:...
>
> Nein. Wenn Busy 1 ist, dann ist das LCD noch beschäftigt.

das meine ich ja.

andi r16,0b10000000        ; Busy 0 ?
brne wrcmd10

wenn r16 jetzt den Wert 0b10000000 hat, dann ist das Busy Flag ja 
gesetzt.
Die Abfrage darunter sorgt nun dafür, dass die subroutine 2wrcmd10" 
verlassen wird.
Das möchte ich aber erst, wenn das Busy Flag nicht mehr gesetzt ist.
Also breq statt brne?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

' brne wrcmd10' springt zur erneuten Abfrage des Busyflags (Anfang des 
Codebeispiels).

MfG Spess

Autor: Olli R. (downunderthunder42)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ok ich habe jetzt die hier gemachten Verbesserungsvorschläge in die 
Routine eingebracht.
ich habe di Subroutine lcd_busy nach Spess53s Vorschlag geändert.

Die lcd_busy routine rufe ich nun am Ende der lcd_data, am Ende der 
lcd_command und immer nachdem ich die lcd_enable in anderen subroutine 
aufgerufen habe?!

Irgendwie ist da noch der Wurm drin?

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spar dir das Busy und verwende einen Timer. Es gibt etwa 2 Befehle, die 
laenger als sofort gehen, und die erschlaegt man mit dem timer

Autor: Attila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin ziemlicher Anfänger und werde daher hier nur einen kleinen aber 
vielleicht hilfreichen Hinweis geben: Das busy flag kann zwischen den 
beiden nibbles abgefragt werden. Sonst wäre ja, zumindest in meinen 
Augen, die ganze busy flag Abfrage Implementation auch irgendwie 
sinnlos.

Autor: Edding (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Olli R. schrieb:
> und immer nachdem ich die lcd_enable in anderen subroutine
> aufgerufen habe?!

warum das denn?
lcd_enable ist der schnellste teil an der ganzen Geschichte.

dein wait für das busy_flag dauert um Größenordnungen länger.

Abgesehen davon, dass es an der Stelle sowieso falsch ist, und das LCD 
aus dem Takt bringt.

Autor: Edding (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Attila schrieb:
> Das busy flag kann zwischen den
> beiden nibbles abgefragt werden.

Nein.
Um zwischen den beiden Nibbels "umzuschalten", musst du mit E wackeln.
Um Busy auszulesen musst du mit E wackeln. sogar zweimal, da du das 
ganze status-Byte auslesen musst.

Autor: Attila (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Enable stimmt natürlich. Hier meine Version vielleicht hilft 
es ja:

busy:  ldi   temp, 0b00001110  ;Datenleitungen 4-7 als Eingang
  out  DDRD,temp
  cbi  PORTD,3            ;RS=0
  sbi  PORTD,2            ;R/W=1
flag:  sbi  PORTD,1            ;E=1
  nop
  nop
  nop
  in  temp,PIND          ;Oberes nibble einlesen
  cbi  PORTD,1            ;E=0
  rcall  enable            ;E=1"triggert" das untere nibble"
  sbrc  temp,7      ;temp enthält oberes nibble
  rjmp  flag      ;
  cbi  PORTD,2            ;R/W=0
  sbi  PORTD,3            ;RS=1
  ldi  temp, 0b11111110        ;Alle Datenleitungen von PORTD als 
Ausgang
  out    DDRD,temp
  ret

Mir hat es damals "das Genick" gebrochen dass ich nicht daran gedacht 
habe den Port als Ausgang und später als Eingang zu konfigurieren. Wie 
gesagt: Vielleicht hilft es ja!

Autor: Olli R. (downunderthunder42)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok ich glaube ich spar mir das wirklich mit dem Busy.

Zumal das Aufrufen eine Busy-Funktion ja auch ne Menge Befehle 
"verbraucht".

meine jetzige Routine gib leider nur einen Cursor an der Position 2 aus.
Ich habe das mit dem Busy gelöscht und stattdessen delay eingefügt, wie 
ursprünglich auch schon.

In einer weiteren Funktion muss wohl noch ein Fehler sein?

ich habe es mit der ursprünglichen lcdroutines.asm verglichen und konnte 
den Fehler dennoch nicht entdecken?

Heia Jetzt-aber schrieb:
> Spar dir das Busy und verwende einen Timer. Es gibt etwa 2 Befehle, die
> laenger als sofort gehen, und die erschlaegt man mit dem timer

Wie würde man das denn mit nem Timer machen. Ich kenn das jetzt nur mit 
diesen delays?

Autor: Olli R. (downunderthunder42)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok zumindest läuft das Programm mit den delays wieder.

Es ist zwar im Wesentlichen das aus dem Tutorial aber egal.
Ich hab zumindest beim Schreiben ne Menge gelernt.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man hat ja in der Regel eh einen Systemtimer. Mein bevorzugter Timer ist 
jeweils 10ms. Da kann man irgendwas in der Richtung :

bool    DisplayTimerEnable;
byte    DisplayTimer;


interrupt Timer
..
 if DisplayTimerEnable {
  if (DisplayTimer !=0) DisplayTimer--;
 }

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Man hat ja in der Regel eh einen Systemtimer. Mein bevorzugter Timer ist
>jeweils 10ms. Da kann man irgendwas in der Richtung :

>bool    DisplayTimerEnable;
>byte    DisplayTimer;


>interrupt Timer
..
> if DisplayTimerEnable {
>  if (DisplayTimer !=0) DisplayTimer--;
> }

So, und das Ganze jetzt noch mal in Assembler.

MfG Spess

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.