Hallo!!! Ich bin blutiger Anfänger was Assembler und µC angeht. Ich benutzte das AVR Studio 4 und einen ATmega 8 mit 10 Mhz getaktet. Ich würde nun gerne eine (Software)-PWM mit 10 Hz (sodass eine LED blinkt) realisieren. Ich weiß nun nicht richtig, wie ich die Subroutine mit dem Runterzählen von 1.000.000 anstellen soll ( sollte am ende 10Hz entsprechen, oder?). Ich komme mit den Befehlen nicht klar. Aktueller Stand, der so nicht funktioniert, aus der Subroutine "erste" kommt er nicht raus... **************************************************************** .include "m8def.inc" LDI r16, HIGH(RAMEND) ; Oberes Byte OUT SPH,r16 ; an Stapelzeiger LDI r16, LOW(RAMEND) ; Unteres Byte OUT SPL,r16 ; an Stapelzeiger ldi r16, 0b00000001 out ddrb, r16 ; Hauptprogramm Haupt: ;definieren der Register für 1.000.000 .equ ges = 1000000 ;gesamtes register ldi r16, low(ges) ;bit 0-8 ldi r17, byte2(ges) ;bit 8-16 ldi r18, byte3(ges) ;bit 16-24 rcall erste rjmp haupt erste: ;Subtrahieren mit 1 ldi r19, 0x01 sub r16, r19 sbc r17, r19 sbc r18, r19 breq weiter rjmp erste weiter: ; hier wird der Port gesetzt. ldi r16, 0x01 out portb, r16 rjmp haupt ************************************************************* Wie funktioniert das mit dem zählen??? Kann mir da bitte jemand weiterhelfen??? Und Bitte nicht über Sinn oder Unsinn des Programmes diskutieren, es dient lediglich dem lernen von Assembler, das es mit dem integrierten Timer einfacher und vorallem Sinnvoller geht weiß ich auch, Danke!!! MFG
also, deine 24bit zahl zerlegst du in drei achtBit zahlen. jedes register in einem. r18:r17:r16 das ist ok. aber ob das mit dem ...byte(2) geht, glaub ich ne beim rechnen von minus eins: dazu gibt es einen speziellen befehl: DEC register. => siehe instr.summary beim subrahieren der drei register, darfst du das erstmal NUR mit dem niederwertigstens machen, und nur falls du bei dieser rechnung: r16=0 ist und du da jetzt eins abzieht: dann kommt (wegen acht bit) nach der ausführung von dec r16 raus: r16=255 und NUR in diesem fall darfst du vom nächsten (hier r17) eins abziehen!! und geht dieses (r17) von null auf 255, dann im nächsthöheren... also r18... rechne doch mal, wie in der schule gelernt, schriftlich: 104-1. das ergebnis wieder minus eins.. unso weiter, und beobachte, wann du von der nächsthöheren stelle auch was abziehst...
Hallo Gast, 1. "blinken" ist keine PWM 2. wenn Du blinken willst, musst Du auch den Zustand der LED ändern 3. Du musst mehrere Schleifen schachteln Gruss Otto
achja, der port muss auch zurückgesetzt werden, und zwar immer abwechselnd.. am besten du invertierst das portpin immer, mittels XOR
Ok, vielen Dank erstmal. Ich denke, das mit dem blinken wäre mir spästens nachdem der Zähler funktioniert hätte auch aufgefallen :D. und wie realisiere ich das mit dem runterzählen, gibt es dafür bestimmte Befehle, oder muss ich jedes Bit in einer einzelnen Subroutine bis zum Übertrag herunterzählen lassen, steh da gerade etwas auf dem Schlauch, sorry. MFG
Hallo Gast, Du musst nicht mit "SUB" arbeiten, "djnz" ist viel schöner..... Gruss Otto
LDI r18, 255 (15) schleife3: LDI r17, 255 (255) schleife2: LDI r16, 255 (255) schleife1: DEC r16 BRNE schleife1 DEC r17 BRNE schleife2 DEC r18 BRNE schleife3 ... dieser zähler zählt von (255hoch3=16'581'375) bis null runter, dann gehts mit ... weiter.. die drei werte musst du noch anpassen. Die Werte in der Klammer ergeben fast 1Million durchläufe (975375mal)
stimmt.... entschuldigung aber Marke: Dec dekrementieren brne und solange zur Marke springen, wie nicht 0 wäre auch gut.... Gruss Otto
ok vielen Dank, dass sollte mir weiter helfen... wollte gerade schon Fragen, wo ich infos zu "djnz" finde, im Datenblatt ist er schließlich nicht drin... MFG
so, hab jetzt ein neues Programm geschrieben, laut Debugger funktioniert es, die Realität sieht leider anders aus :(. das Oszi zeigt leider auch keine Reaktion, kommt ne komplette Gleichspannung von 5 V raus... Ist mein Controller vielleicht defekt??? Datenübertragung hat alles wunderbar funktioniert... Vielleicht findet jemand einen Fehler, ich danke euch schonmal im voraus, wie immer eben ;)... MFG ************************************************************************ ** ;definitionsdatei .include "m8def.inc" ; einrichten des Stacks LDI r16, HIGH(RAMEND) ; Oberes Byte OUT SPH,r16 ; an Stapelzeiger LDI r16, LOW(RAMEND) ; Unteres Byte OUT SPL,r16 ; an Stapelzeiger ;Ausgänge konfigurieren ldi r16, 0b00000001 out ddrb, r16 ; Hauptprogramm Haupt: ;auschalten des ausgangs clr r19 out portb, r19 .def byt1 = r20 ;R16 .def byt2 = r21 ;R17 ; Hier wird runtergezählt bis 0, und dann der Ausgang gesetzt. ; bewerten der Register ; *********hier die Zeit einstellen, anhand der werte der bits********** ; ********************************************************************** ldi byt1, 64 ;bit 0-8 (entspricht R16) ldi byt2, 13 ;bit 8-16 (entspricht R17) ldi r18, 3 ;bit 16-24 ;die werte noch in die register schreiben mov r16, byt1 mov r17, byt2 ;das ergibt 1 mio ( 00001111.01000010.01000000 (24bit)) rcall schleife1 ; bit 0-8 herunterzählen schleife1: dec r16 breq schleife2 rcall schleife1 schleife2: mov r16, byt1 dec r17 breq schleife3 rcall schleife1 schleife3: mov r16, byt1 mov r17, byt2 dec r18 breq einschalten rcall schleife1 ;port einschalten nach ...mio durchläufen einschalten: ldi r19, 0x01 out portb, r19 rcall haupt ************************************************************************ **
oder ist der Einschaltimpuls einfach zu kurz??? Ich meine wenn der 5-10 Zyklen angeschlatet ist, entspricht das vielleicht 0,5 - 1 µs...
ok, ich habe es endlich... der stack ist immer übergelaufen... so funktioniert es.. sorry für die schlechten kommentare, habe ich irgendwie hingepfuscht. werde das demnächst noch verbessern, das man tastverhältnis und die zeit einfacher programmieren kann... **************************************************************** ;definitionsdatei .include "m8def.inc" ; Hauptprogramm Haupt: ;ausschalten ldi r19, 0x00 out portb, r19 .def byt1 = r20 ;R16 .def byt2 = r21 ;R17 .def byt3 = r25 ;R22 .def byt4 = r26 ;R23 ; Hier wird runtergezählt bis 0, und dann der Ausgang gesetzt. ; bewerten der Register ; *********hier die Zeit einstellen, anhand der werte der bits********** ; ********************************************************************** ldi byt1, 255 ;bit 0-8 (entspricht R16) ldi byt2, 255 ;bit 8-16 (entspricht R17) ldi r18, 100 ;bit 16-24 ;ausschalten ldi byt3, 255 ;0-8 bit zum ausschalten ldi byt4, 255 ;8-16 bit zum ausschalten ldi r24, 100 ;16-24 bit zum ausschalten ;die werte noch in die register schreiben mov r16, byt1 mov r17, byt2 ;das ergibt 1 mio ( 00001111.01000010.01000000 (24bit)) ;einschalten schleife1: dec r16 breq schleife2 brne schleife1 schleife2: mov r16, byt1 dec r17 breq schleife3 brne schleife1 schleife3: mov r16, byt1 mov r17, byt2 dec r18 breq einschalten brne schleife1 ;port einschalten nach ...mio durchläufen einschalten: ;Ausgänge konfigurieren ldi r23, 0b00000001 out ddrb, r23 nop ldi r19, 0x01 out portb, r19 ; ausschalten schleife4: dec r22 breq schleife5 brne schleife4 schleife5: mov r22, byt3 dec r23 breq schleife6 brne schleife4 schleife6: mov r23, byt4 dec r24 breq haupt brne schleife4 ******************************************************************
Erzählt doch keinen Schmarrn, Subtraktion geht natürlich 24-bittig, also weg mit den ollen umständlichen 8Bit-Schleifen, mach es so:
1 | ... |
2 | erste: |
3 | ;Subtrahieren mit 1 |
4 | subi r16, byte1(1) |
5 | sbci r17, byte2(1) |
6 | sbci r18, byte3(1) |
7 | brne erste |
8 | |
9 | weiter: |
10 | ... |
Peter
ok vielen Dank, wieder mal. werde das heute Abend einmal ausprobieren. Die Schleiferei und Verzweigerei ist doch etwas umständlich ;). MFG
ok, habe das jetzt mit dem zählen auch hinbekommen, ist schoneinmal übersichtlicher geworden. Vollständigkeitshalber der Code nochmal... ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;definitionsdatei .include "m8def.inc" ;definieren der Ein/Ausgänge ldi r16, 1 out ddrb, r16 ; Hauptprogramm Haupt: ;definieren der Variablen ;Variable zum Einschalten der LED .equ ein = 200000 ;NOP takte ldi r16, low(ein) ldi r17, byte2(ein) ldi r18, byte3(ein) ;Variable zum Ausschalten der LED .equ aus = 200000 ;NOP takte ldi r19, low(aus) ldi r20, byte2(aus) ldi r21, byte3(aus) zaehlen: ;Zählen fürs Einschalten ;herunterzählen subi r16, byte1(1) sbci r17, byte2(1) sbci r18, byte3(1) sbrs r18, 0 breq einschalten rjmp zaehlen einschalten: ;LED einschalten ldi r16, 1 out portb, r16 zaehlen2:;Zählen fürs Ausschalten ;herunterzählen subi r19, byte1(1) sbci r20, byte2(1) sbci r21, byte3(1) sbrs r21, 0 breq ausschalten rjmp zaehlen2 ausschalten: ;LED ausschalten ldi r16,0 out portb, r16 rjmp haupt ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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.