Hallo zusammen, irgendwie hab ich nach stundenlangem Googlen, ausprobieren etc. keinen Erfolg gehabt, bevor ich ganz verzweifle, wende ich mich lieber an die Profis... Ich möchte eine Schleife programmieren, die mir in etwa 1ms Pause erzeugt, dieser möchte ich dann über einen Parameter die Anzahl der Durchläufe (sprich: die Anzahl der ms) übergeben. Mein Ansatz hat leider nicht funktioniert: [assembler] delay: LDI r17, 2 dely1: LDI r16, 166 dely: DEC r16 BRNE dely DEC r17 BRNE dely1 DEC r25 BRNE delay RET [/assembler] Meine Idee war folgende: DEC und BRNE brauchen zusammen 3 Takte, wird diese Schleife 165x ausgeführt, haben wir ungefähr 500 Takte. Das Ganze dann 2x durchlaufen entspricht 1000 Takte - also bei 1Mhz wäre das 1ms Und im Register r25 steht die Anzahl der Gesamtdurchläufe, sprich die Anzahl der ms... aber ich komm nicht auf 1ms wenn ich in r25 ne 2 reinschreibe-wo liegt mein Denkfehler? Und wenn ich in einer Variablen fq=4000000 die Taktfrequenz bei einem externen Quarz drinstehen habe, wie mache ich es am geschicktesten, dass ich obige Schleife dann auch 4x so oft durchlaufen lasse? Irgendwie hab ich heut schon den halben Tag vertan, ohne auf ein Ergebnis zu kommen... vielen Dank also schon mal für Eure Hilfe!!
Brne ist doch erst wenn der wert Negativ ist oder? und 2 minus 1 minus 1 = 0 und nicht negativ, also würd ich sagen schreib einfach mal 1 rein. vielleicht kommst du dann auf deine ms. Nur eine Idee. MFG Marc
Ist doch Easy: .equ AVRTakt=8 Wait1000uS: ldi r24,low(1000*AVRTakt/4) ldi r25,high(1000*AVRTakt/4) WaituS: sbiw r25:r24,1 brne WaituS ret In AVRTakt einfach die tatsächliche Frequenz in MHz definieren, fertig. Kann auch so was wie 3.62345 etc. sein. Ist zwar jetzt nicht auf den Takt genau aber es reicht. Für ziemlich genau gibt es sowieso nur Timer-Interrupt. Für z. B. 50µS läßt sich das erweitern mit Wait50uS: ldi r24,low(50*AVRTakt/4) ldi r25,high(50*AVRTakt/4) rjmp WaituS Die Formel N*AVRTakt/4 rechnet die Anzahl der Schleifendurchläufe unter Berücksichtung, das ein Durchlauf 4 Takte dasuert, aus. Bei 8MHz sind dann 65535 / 8 * 4 = 32,7675 mS möglich. Ließe sich für eine längere Zeit auch auf 24 oder 32Bit-Zählung erweitern. MfG Andi
Wahrscheinlich denk ich da zu kompliziert... und es geht auch einfacher... Was du meinst, ist aber vermutlich BRMI (Branch if Minus), BRNE ist Branch if not equal, also wenn das Ergebnis ungleich 0 ist...
Oder so: WaitmS: ldi r24,low(1000*AVRTakt/4-1) ldi r25,high(1000*AVRTakt/4-1) WaitmS1: sbiw r25:r24,1 brne WaitmS1 nop dec r16 brne WaitmS ret In r16 die Anzahl der mS und dann aufrufen. Das NOP ist zum Ausgleich wegen dem Zyklus von 4 Takten. MfG Andi
lol - also soo easy ist das leider nicht... zumindest für mich nicht ;) Ich wusste ned mal dass man so einfach zwei Register konkatenieren kann, bisher hab ich nur einen HC68011 programmiert, und da ist die Umstellung auf AVR schon ziemlich groß... Also prinzipiell ist dein Code supereinfach und funktioniert auch (fast) gut... ich hab nur das Problem dass die Ausgabe auf dem µC um den Faktor 4 zu schnell vor sich geht. Im Simulator läuft der µC mit 4 Mhz, stelle ich AVRTakt auf 4 ein, kommt ziemlich genau 1ms raus. Der reale µC hat zwar einen 4Mhz Quarz dran, der aber noch nicht aktiviert ist, läuft also mit den internen 1Mhz. Und bei AVRTakt=1 und hundertfachem Schleifendurchlauf blinkt er 4x/Sekunde... woran kann das liegen? Ansonsten vielen Dank für den Code, der hat mir schon einiges an Ärger erspart!!
Denk daran das der Aufruf der Unterroutine auch nochmal 7 takte benötigt (rcall + ret) ;-)
Deine Routine von oben würde so aussehen:
1 | ldi r25, 1 |
2 | rcall delay ;1011 takte |
3 | |
4 | delay: ;------------------------ |
5 | LDI r17, 2 ;--------------- |
6 | |
7 | dely1: |
8 | LDI r16, 166 ;------- |
9 | dely: ; 498 t 1002t 1004t |
10 | DEC r16 ; |
11 | BRNE dely ;------- |
12 | |
13 | DEC r17 |
14 | BRNE dely1 ;--------------- |
15 | |
16 | |
17 | DEC r25 |
18 | BRNE delay ;----------------------- |
19 | RET |
Der Aufruf würde also 1011 takte verschwenden wenn r25 = 1 wäre.
Na ja, bei einer Pause von 1mS braucht man glaube ich nicht über 7 Takte (1µS) zu reden. @Ithamar Garbe (Antimon): Wenn Du sicher bist, das der AVR mit 1MHz läuft, hast Du dann AVRTakt auf 1 eingestellt? MfG Andi
Im Anhang gibts nen Schleifengenerator. Hat bisher perfekt funktioniert. Gruss Mika
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.