Hallo zusammen, ich bin gerade dabei das angebotene AVR Tutorial durchzuarbeiten. Ich bin jetzt leider beim LCD Display ansteuern hängen geblieben. Die Initialisierung für den 4 Bit Modus macht mir Probleme. Mein Problem ist wie ich Zeitverzögerungen in Assembler programmieren kann. Mein verwendeter Mega8 betreibe ich mit dem internen Takt von 1MHz. Das Prinzip ist mir klar ich muss so viel Rechenaufwand in den Code einbringen, bis ich zum nächsten Steuerungsbefehl komme, dass ich die gewünschte Zeitverzögerung aus dem Datenblatt der LCD Anzeige erreiche. Wie baue ich eine Verzögerung von von z.B. von 5 ms ein? In der Theorie muss ich dem Controller 5000 Takte Arbeit geben. Wie realisiere ich das Ganze platzsparend? Eine kleine weitere Frage: Die 4 Bit Initialisierung muss jedes mal nach Einschalten durchgeführt werden, oder muss das Ganze nur einmal erfolgen? Vielen Dank für die Hilfe und die Geduld! Beste Grüße, Florian
Florian S. schrieb: > In > der Theorie muss ich dem Controller 5000 Takte Arbeit geben. Wie > realisiere ich das Ganze platzsparend? Einfach zwei ineinander verschachtelte 8-Bit-Zähler. Der "innere" Zähler zählt von 0xFF bis 0, der äußere von 0x13 bis 0 (oder so). Florian S. schrieb: > Die 4 Bit Initialisierung muss jedes mal nach > Einschalten durchgeführt werden, oder muss das Ganze nur einmal > erfolgen? Nur einmal am Anfang (bzw. nachdem das Display Spannung kriegt).
Florian S. schrieb: > Mein Problem ist wie ich Zeitverzögerungen in Assembler programmieren > kann. Mein verwendeter Mega8 betreibe ich mit dem internen Takt von > 1MHz. Das Prinzip ist mir klar ich muss so viel Rechenaufwand in den > Code einbringen, bis ich zum nächsten Steuerungsbefehl komme, dass ich > die gewünschte Zeitverzögerung aus dem Datenblatt der LCD Anzeige > erreiche. Wie baue ich eine Verzögerung von von z.B. von 5 ms ein? In > der Theorie muss ich dem Controller 5000 Takte Arbeit geben. Wie > realisiere ich das Ganze platzsparend? Irgendwie verstehe ich deine Frage nicht. All diese Dinge sind im Tuorial ausgeführt und in Form von Code gezeigt. Der beschreibende Text im Tutorial-Artikel ist nicht dort, damit es hübscher aussieht. > Eine kleine weitere Frage: Die 4 Bit Initialisierung muss jedes mal nach > Einschalten durchgeführt werden, oder muss das Ganze nur einmal > erfolgen? Jedes mal, wenn Spannung angelegt wird. Das LCD merkt sich diese Einstellung nicht.
Okay vielen Dank für die schnelle Hilfe ich werd mich nochmal einlesen. Beste Grüße
So jetzt meld ich mich doch nochmal. Wie ich vorher übersehen hab, ist die Verzögerungschleife in den Standartroutinen. Nun liegt das Problem im verstehen der paar Zeilen. Hier der Ausschnitt:
1 | delay5ms: ; 5ms Pause (bei 4 MHz) |
2 | ldi temp1, $21 |
3 | WGLOOP0: ldi temp2, $C9 |
4 | WGLOOP1: dec temp2 |
5 | brne WGLOOP1 |
6 | dec temp1 |
7 | brne WGLOOP0 |
8 | ret ; wieder zurück |
Meine Interpretation lautet folgendermaßen: 1. Lade in temp1, 0x21 2. Lade in temp2, 0xC9 3. Dekrementiere temp2 4. Wenn temp2 nicht 0 ist, springe auf WGLOOP1 und wiederhole 3. ansonsten 5. Dekrementiere temp1 6. Wenn temp1 nicht 0 ist, springe auf WGLOOP1 und wiederhole somit 1-5. ansonsten 7. zurück ins Hauptprogramm Ein Blick in die Instruction Set sagt mir dass alles 1 Takt braucht bis auf brne, der Befehl braucht 1 bis 2 Takte. Meine Frage: Gibt es eine Laufzeitformel für solche Schleifentypen? Mir schwebt ne Funktion die mir die Verzögerung in irgendeiner Sekundeneinheit ausgibt in Abhängigkeit der eingegebenen Registerwerte und dem Versorgungstakt. Die Laufzeit ist ja zusätzlich noch abhängig wie viele Befehle in den einzelnen Schleifen stehen, diese würd ich aber als Konstanten für genau diesen Schleifentyp annehmen, da das denke ich ne Standardschleife ist. Wenn diese Formel existiert, hab ich sie bis jetzt noch nicht gefunden. Ansonsten welchen Wert muss ich denn für brne nehmen 1 oder zwei Takte um so eine Formel selbst aufzustellen? Vielen Dank für die Hilfe. Ich weiß sind doch wahrscheinlich sehr banale Fragen, aber tu mir etwas schwerer wie mir scheint. Beste Grüße, Florian
Florian S. schrieb: > Meine Frage: Gibt es eine Laufzeitformel für solche Schleifentypen? Für die Herstellung 1 Schachtel brauchst du 2 Minuten. WIe lange brauchst du für 35 Schachteln? ( Bzw. Was dich dann anders rum interessiert: Wieviele Schachteln kannst du in 60 Minuten machen? ) > und dem Versorgungstakt. Die Laufzeit ist ja zusätzlich noch abhängig > wie viele Befehle in den einzelnen Schleifen stehen, diese würd ich aber > als Konstanten für genau diesen Schleifentyp annehmen Nö. Die weißt du doch. Wenn du 25 in ein Register lädst und in der Schleife das Register um 1 runterzählst und zum Schleifenanfang gehst, wenn noch nicht 0 erreicht, wie oft wird dann die Schleife durchlaufen?
Okay meine eigene Formel lautet:
1 | Tdelay = ( 1 + 1 + Werttemp1 * 2 * Werttemp2 * 2 + 4 ) * 1/f |
2 | |
3 | Tdelay = ( 6 + Werttemp1 * Werttemp2 * 4 ) * 1/f |
Kurze Erklärung: 1+1 : Initialisierung der Zählerregister: *2 : Da jeweils in jeder Schleife 2 Befehle stehen +4: ret braucht 4 Takte Diese Formel wurde unter der Annahme erstellt, dass brne 1 Takt braucht um abgearbeitet zu werden. Mit zwei wäre die Formel entsprechend:
1 | Tdelay = ( 6 + Werttemp1 * Werttemp2 * 9 ) * 1/f |
Kann man die Laufzeit so berechnen, oder hab ich nen Denkfehler? Ich hab nachgerechnet mit beiden Formeln kommt der falsche Wert für gewollte 5 ms Verzögerung raus. Mit der ersten sinds 6.6 ms mit der zweiten 14.9 ms bei eingesetzten Werten Werttemp1 = 33 Werttemp2 = 201 und f = 4MHz. (alles natürlich dezimal). Das kann jetzt daran liegen, dass meine Formeln falsch sind oder, dass die Anwendung nicht arg laufzeitkritisch ist und somit großzügig gerechnet wurde, hauptsache die Mindestlaufzeitverzögerung wurde erreicht. Beste Grüße, Florian
Florian S. schrieb: > (alles natürlich dezimal). Das kann jetzt daran liegen, dass meine > Formeln falsch sind oder, dass die Anwendung nicht arg laufzeitkritisch > ist und somit großzügig gerechnet wurde, hauptsache die > Mindestlaufzeitverzögerung wurde erreicht. Kann mich so dunkel erinnern, dass ich da ziemlich genau gerechnet habe. Probier halt deine Formeln mal mit einfacheren Zahlen aus. Jede der beiden Schleifenkonstanten sei 1. Was kommt dir in der Formel raus? Spiel den Code mit Papier und Bleistift durch, wieviele Takte hast du verbraucht? Vergleiche die Ergebnisse.
Okay meine Fehlerquellen sind in diesen Fall: 1. nicht berücksichtigter Sprung zur Routine macht +3 2. Fallunterscheidung bei brne 1/2 Takte. Wobei ich da nicht weiß, wann ich was nehmen soll. Entweder der Befehl braucht immer einen Takt oder immer 2 Takte, oder es wird unterschieden, ob die die Bedingung erfüllt ist oder nicht. Vielleicht kann mir da jemand helfen in der Instruction Set steht dazu nichts (ich habs zumindest nicht gefunden keine Fußnote nichts). 3. Ich hab ein falsches Bild des Ablaufs. Ich hab ihn weiter oben kurz beschrieben, vielleicht ist der falsch. Beste Grüße, Flo
Florian S. schrieb: > 2. Fallunterscheidung bei brne 1/2 Takte. Wobei ich da nicht weiß, wann > ich was nehmen soll. Entweder der Befehl braucht immer einen Takt oder > immer 2 Takte, oder es wird unterschieden, ob die die Bedingung erfüllt > ist oder nicht. Vielleicht kann mir da jemand helfen in der Instruction > Set steht dazu nichts (ich habs zumindest nicht gefunden keine Fußnote > nichts). Aus dem Gedächnis: 1 Takt wenn die Bedingung falsch ist, also Register==0 und nicht gesprungen wird. 2 Takte wenn gesprungen wird.
Karl Heinz Buchegger schrieb: > Florian S. schrieb: > >> (alles natürlich dezimal). Das kann jetzt daran liegen, dass meine >> Formeln falsch sind oder, dass die Anwendung nicht arg laufzeitkritisch >> ist und somit großzügig gerechnet wurde, hauptsache die >> Mindestlaufzeitverzögerung wurde erreicht. > > Kann mich so dunkel erinnern, dass ich da ziemlich genau gerechnet habe. Das passt schon. Laut Simulator werden (ohne den Return) 19998 Takte verbraucht, was bei 4Mhz einer Zeit von 4.9995 ms entspricht. Deine Formeln sind falsch.
spess53 schrieb: > Hi > > Suche mal nach: > > AVR delay loop generator > > MfG Spess Was Spess sagt. -> http://bretm.home.comcast.net/~bretm/avrdelay.html Gruß John
John Bauer schrieb: > spess53 schrieb: >> Hi >> >> Suche mal nach: >> >> AVR delay loop generator >> >> MfG Spess > > Was Spess sagt. -> > > http://bretm.home.comcast.net/~bretm/avrdelay.html grundsätzlich richtig. Nur sind das Dinge, die er eigentlich selbst können sollte. Der Generator bringt Komfort ersetzt aber nicht die Übung.
Hi brne braucht 2 Takte um wieder zum dec zurück zu springen und einen Takt wenn das Register Null ist. Macht 3n-1 Takte. Dazu kommt ein Takt für das Laden des Registers. Damit braucht ldi rxy,n aaa: dec rxy brne aaa genau 3n Takte. MfG Spess
Vielen Dank für die vielen Tipps. Der Generator ist super, erleichtert einem die Arbeit wesentlich. Ich würde aber trotzdem gerne eine expilizite Formel herleiten, nur hab ich bis jetzt den Trick hinter der geschachtelten Schleife nicht gesehen. Bis jetzt hab ich: 1. 2*1 Takt für Werte ins Register laden 2. 3 Takte für den Sprung in die Routine 3. 4 Tate für den Sprung zurück ins Hauptprogramm 4. Danach wird die innerste Schleife in einem Durchlauf mit 3 Takten durchlaufen wenn das Register danach nicht den Wert 0 hat. Also ins gesamt dann 3 * ( temp2 - 1 ) + 2 = 3 * temp2 - 1 5. Die Verschachtelung hab ich so gelöst ( 3 * temp2 - 1 ) * temp1 die innere Schleife wird ja mit der Anzahl der von temp1 durchlaufen. 5. die äußere Schleife wird wie 4 durchlaufen 6. nach jedem mal, nachdem die Innere Schleife runtergelaufen ist wird die äußere durlchlaufen und solange die Beding nicht erfüllt ist, wird wieder zum Register temp2 gesprungen, somit noch +temp2-1 Insgesamt macht das dann:
macht dann zusammengefasst:
Bei mir kommen jetzt nur leider 20005 Takte raus(Ich glaub solangsam blamier ich mich :-D). Über noch ne Anregung was nicht stimmt wär ich nochmals sehr dankbar. Beste Grüße, Florian
Um die Verwirrung zu vervollständigen: Man kann die Taktfrequenz des AVR auch relativ einfach ändern – auch beim internen RC-Oszillator. Manche AVR lassen sich dann mit z.B. 500 Hz betreiben – das vereinfacht die Warteschleifen dann beträchtlich. Außerdem sinkt der Stromverbrauch deutlich.
Florian S. schrieb: > Vielen Dank für die vielen Tipps. Der Generator ist super, erleichtert > einem die Arbeit wesentlich. Ich würde aber trotzdem gerne eine > expilizite Formel herleiten, nur hab ich bis jetzt den Trick hinter der > geschachtelten Schleife nicht gesehen. Schreibs dir mal so an ldi temp1, $21 > A ------------- WGLOOP0: ldi temp2, $C9 WGLOOP1: dec temp2 brne WGLOOP1 > B ------------- dec temp1 brne WGLOOP0 Wie Spess schon gezeigt hat, benötigt der Teil von >A bis >B genau 3n Takte, wobei sich das n hier ldi temp2, $C9 wieder findet. Ein Durchgang durch diesen Teil dauert also ($C9 ist gleich 201) 3 * 201 Takte. Macht in diesem Fall 603 Takte. Gut. Wie oft wird dieser innere Teil wiederholt? Der wird $21 mal wiederholt. $21, das ist dezimal 33. D.h. der innere Teil (von >A bis >B wird in Summe mit 33 * 603 Takten zu Buche schlagen. Das ergibt 19899 Takte Gut. Das ist der Anteil des inneren Teils. Wieviel kommt da noch für den äusseren Teil dazu? Der dec wird 33 mal ausgeführt und braucht jeweils 1 Takt. der brne wird ebenfalls 33 mal ausgeführt. 32 mal braucht er 2 Take und 1 mal 1 Takt. d.h. da ist noch 19899 + 33 für den dec + 64 für den brne, wenn er springt + 1 für den brne, wenn er nicht springt -------- 19997 und dann fehlt noch der ldi temp1, $21 der nur ein einziges mal ausgeführt wird. 19997 1 ------- 19998 und genau dasselbe sagt auch der Simulator, der auf exakt die gleiche Anzahl kommt. Allerdings in dem er das Programm abarbeitet. Nachdem jetzt der prinzipielle Vorgang korrekt ist, gehst du her und fasst das ganze in eine Formel :-)
Hi n sei der Wert der inneren und m der Wert der äußeren Schleife. Dann ist 3m die Anzahl der Takte der äußeren Schleife. Dazu kommen m*3n Takte für die innere Schleife. Damit ist die Summe der Takte 3m+m*3n. So, und jetzt erstellst du die Formel für ldi r1,m aaa: ldi r2,n bbb: nop dec r2 brne bbb nop dec r1 brne aaa MfG Spess
Dann komm ich ja auf die gleiche Anzahl nur hab ich die Sprünge in und wieder zurück noch mit berücksichtigt. Okay passt dann wars ja garnicht falsch. Vielen dank. Beste Grüße, Florian
Florian S. schrieb: > Dann komm ich ja auf die gleiche Anzahl nur hab ich die Sprünge in und > wieder zurück noch mit berücksichtigt. Okay passt dann wars ja garnicht > falsch. Vielen dank. Na, dann gratulier ich.
Man muß keine kryptischen Zahlen hinschreiben. Der Assembler soll gefälligst selber Konstanten ausrechen, man schreibt nur die Formeln hin. Zwar nur Ganzzahl 32Bit, aber das sollte reichen. Hier mal ein Delay-Macro: Beitrag "Re: AVR: Delay 7 ... 65542 Zyklen" Peter
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.