Hi, erstmal danke für des tut mit PWM-software! Dazu hab ich jetzt ein paar verständnisprobleme! Hier erstmal den code: timer0_overflow: ; Timer 0 Overflow Handler inc PWMCount ; den PWM Zähler von 0 bis cpi PWMCount, 128 ; 127 zählen lassen brne WorkPWM clr PWMCount WorkPWM: ldi temp, 0b11000000 ; 0 .. Led an, 1 .. Led aus cp PWMCount, ocr_1 ; Ist der Grenzwert für Led 1 erreicht brlt OneOn ori temp, $01 OneOn: cp PWMCount, ocr_2 ; Ist der Grenzwert für Led 2 erreicht brlt TwoOn ori temp, $02 TwoOn: cp PWMCount, ocr_3 ; Ist der Grenzwert für Led 3 erreicht brlt ThreeOn ori temp, $04 ThreeOn:cp PWMCount, ocr_4 ; Ist der Grenzwert für Led 4 erreicht brlt FourOn ori temp, $08 FourOn: cp PWMCount, ocr_5 ; Ist der Grenzwert für Led 5 erreicht brlt FiveOn ori temp, $10 FiveOn: cp PWMCount, ocr_6 ; Ist der Grenzwert für Led 6 erreicht brlt SetBits ori temp, $20 SetBits: ; Die neue Bitbelegung am Port ausgeben out PORTB, temp reti Was bedeutet ori temp, $10 oder so??? also jetzt nicht bezogen auf die zahl sondern auf die ganze zeile! Die LEDs leuchten erst wenn das Programm SetBits oder versteh ich des falsch??
> Was bedeutet ori temp, $10
Das bedeutet, dass der Inhalt des Registers temp mit der (Hexadezimal-)
Zahl 10h (bitweise) ODER-verknüpft wird. Mit anderen Worten: Das Bit
Nummer 4 in temp wird gesetzt (egal welchen Wert es vorher hatte),
während alle anderen Bits im Register unverändert bleiben.
ori verknüpft ein register mit einer Zahl (daher das i in ori - immediate - direkt angegeben) mittels einer ODER Verknüpfung. Und zwar macht ori das Bit für Bit Die Wahrheitstabelle für ODER A B Ergebnis ---------------------- 0 0 0 1 0 1 0 1 1 1 1 1 (Das Ergebnis ist dann 1, wenn entweder A oder B oder beide 1 sind) Man erkennt aber auch: Das Ergebnis ist nur dann 0, wenn weder A noch B eine 1 aufweisen. Und das benutzt man hier: Sei A irgendein Bit im Register und B das korrespondierende Bit in der Zahl, dann taucht im Ergebnis auf jeden Fall eine 1 auf, wenn B den Wert 1 hat, unabhängig davon welchen Wert A hatte (in der Wahrheitstabelle kontrollieren!). Wenn A sowieso schon den Wert 1 hat, dann ist auch das Ergebnis 1, diesmal unabhängig von B. Bsp: Im Register steht zb. die Bitkombination 01000100 Und die Zahl habe die Bitkombination 00010001 dan ergibt die ODER Verknüpfung (einfach untereinanderstehende Bits laut Wahrheitstabelle miteinander verknüpfen) 01010101 man erkennt: Dort wo ursprünglich im Register bereits eine 1 war, ist auch im Ergebnis eine 1. Dort wo in der Zahl eine 1 ist kommen im Ergebnis 1-en dazu. In Summe kann man also mit einer ODER Verknüpfung gezielt Bits in einem Register setzen. (Ich seh schon, da wird im Tutorial mal eine Seite über logische Verknüpfungen fällig)
Hallo Joachim Geiger, zu Frage 2:
1 | SetBits: ; Die neue Bitbelegung am Port |
2 | ausgeben |
3 | out PORTB, temp |
Macht genau was da steht: Der Inhalt von "temp" wird auf PORTB ausgegeben.
Joachim Geiger wrote: > Die LEDs leuchten erst wenn das Programm SetBits oder versteh ich des > falsch?? Das verstehst du schon richtig. Die Idee ist folgende: Mittels PWMCount wird ein Zeitraster erzeugt. Es gibt also den Zeitpunkt 1, Zeitpunkt 2, Zeitpunkt 3 etc. Die OCR Werte geben an, zu welchem Zeitpunkt eine LED ausgeschaltet werden soll. Enthält OCR den Wert 3, dann bedeutet das, das die LED nur während der Zeitpunkte 0, 1, 2 leuchten soll. Zu allen anderen Zeitpunkten (3 bis 127) soll sie dunkel sein. Enthält OCR den Wert 7, dann soll die LED während der Zeitpunkte 0, 1, 2, 3, 4, 5, 6 leuchten. Im zweiten Fall leuchtet sie daher länger als im ersten Fall. Und genau das wollen wir ja: Wir wollen das Verhältnis von Einschaltzeit zu Auszeit einstzellen können. Bei der Verschaltung im Tutorial leuchtet eine LED genau dann, wenn der zugehörige Port Pin eine 0 aufweist. Also beginnt die PWM Abfrage damit, dass in einem Register einfach mal alle Bits (bis auf die obersten 2, die sind nicht benutzt) auf 0 gesetzt werden. Würde man diesen Registerinhalt so auf den Port ausgeben, dann würden alle Leds leuchten. Aber jetzt kommt ja noch die Abfragekaskade. Sie vergleicht den OCR Wert mit dem PWMCount (stellt also fest, ob der vorgegebene Zeitpunkt bereits erreicht oder überschritten wurde). Ist der Zeitpunkt noch nicht erreicht, dann passiert nichts mit dem Bit. Ist der Zeitpunkt erreicht oder überschritten, so wird in diesem Register mittels ori das zugehörige Bit auf 1 gesetzt. Nachdem die Abfragekaskade durchgelaufen ist, enthält also dieses Register für alle Led deren Zeitpunk noch nicht erreicht ist eine 0 und für alle Led deren Zeitpunkt bereits erreicht oder abgelaufen ist eine 1. (Nochmal: bei 0 leuchtet die zugehörige Led, bei 1 ist sie dunkel) Und das wird in einem Rutsch auf den Port ausgegeben. Man hätte das Ganze auch gezielt direkt mit Einzelbit Port-Setz- und Rücksetzbefehlen machen können (für Ports gibt es die), aber wenn du das mal probierst stellst du fest, dass dadurch das Program auch nicht kürzer wird sondern, ganz im Gegenteil, eine Menge Sprünge mehr hinzugekommen wären.
Danke für eure antworten jetzt versuch ich mal mein glück! ja die logischen verknüpfungen sind schon klar aber ich stand auf dem schlauch was zb die 10 bedeutet aber des is ja 1010. Des war einfach nur des was mich verwirrt hat. ich könnt doch anstatt dem $10 auch 0b00001010 schreiben oder?? mir ging es darin eigentlich nur um die Zahl da hinten dran weil ich den zusammenhang zwischen der zahl und dem befehl nicht ganz verstanden hab. aber das "$" Zeichen gibt ja einfach eine dec. zahl binär oder hex an oder??
> ich könnt doch anstatt dem $10 auch 0b00001010 schreiben oder??
Nö, $10 ist 0b00010000.
"$10" ist eine alternative Schreibweise für "0x10" und das ist eine Hexadezimalzahl. Dezimalzahlen schreibt man ohne "$" oder "0x". 0x10 in Dezimal ist 16.
Also ich hab jetzt im Anhang mal mein erstes Prog rein gehängt. Sorry aber wie gesagt ich bin noch relativ neu. Ich komm irgendwie nicht mehr weiter. Wäre nett wenn einer nur mal kurz drüber schaut und ein kurzes statement bzw. vorschläge abgibt!!!! Danke schon mal
Ah jetzt ich versteh!! :-) Oh des mit den #, (), $ ... Zeichen is voll verwirrend. wir Programmieren in der Schule mit nem Motorolla und da machen wir alles ganz anders aber so wie es mit dem Amtel geh versteh ich zumindest ein wenig.
> ja die logischen verknüpfungen sind schon klar aber ich stand auf dem > schlauch was zb die 10 bedeutet aber des is ja 1010. Des war einfach nur > des was mich verwirrt hat. ich könnt doch anstatt dem $10 auch > 0b00001010 schreiben oder?? Nein nicht ganz, der Unterschied zwischen 10 und $10 ist das Zahlensystem. 10 = Dezimal = 0b00001010 $10 = Hexadezimal = 0b00010000
kann mir keiner weiterhelfen mit der datei da ich absolut nicht mehr weiter komme!!!
Ich seh nirgends den globalen PWM Counter. Ich seh auch nirgends, dass du den Timer Interrupt angeschlossen hättest. Was du anscheinend überhaupt nicht begriffen hast ist, dass die ganze PWM im Hintergrund von einem Timerinterrupt erledigt wird. Du musst nur dafür sorgen, dass ein Timer in regelmässigen Abständen die PWM Funktion aufruft. Mehr nicht. Warum spielst du nicht einfach mal ein bischen mit dem im Tutorial angeführten Programm rum, bevor du versuchst sie in dein bestehendes Programm einzubinden.
Was ist dein Problem? Alle Fragenkreise sind im Beispielprogramm im Tutorial ausgeführt: * Wie man den Timer aufsetzt * Wie man den Interrupt in den Interrupt Vektor einbaut. * Was die Interrupt funktion machen muss. Du wirst diese 3 Themenkreise ja wohl noch alleine in dein Programm übernehmen können.
ok dann schau ich es mir nochmal genauer an ich hab des nur nicht so ganz kapiert mit den interrupts!!
Ist ganz simpel: Für einen Interrupt brauchst du 1) Einen Eintrag in der Interrupt Vektor Tabelle 2) Das Freigabebit für den entsprechenden Interrupt muss gesetzt sein 3) die globalen Interrupts müssen mittels sei freigegeben sein 4) Eine Funktion die den Interrupt bearbeitet ad 1) Das ist deine Interrupttabelle
1 | ;interrupt vectors |
2 | |
3 | rjmp init ;reset vector address |
4 | reti ;External Interrupt0 Vector Address |
5 | reti ;External Interrupt1 Vector Address |
6 | reti ;Input Capture1 Interrupt Vector Address |
7 | reti ;Output Compare1A Interrupt Vector Address |
8 | reti ;Output Compare1B Interrupt Vector Address |
9 | reti ;Overflow1 Interrupt Vector Address |
10 | reti ;Overflow0 Interrupt Vector Address |
11 | reti ;SPI Interrupt Vector Address |
12 | rjmp get_byte ;UART Receive Complete Interrupt Vector Address |
13 | reti ;UART Data Register Empty Interrupt Vector Address |
14 | reti ;UART Transmit Complete Interrupt Vector Address |
15 | reti ;Analog Comparator Interrupt Vector Address |
16 | reti ;External Interrupt2 Vector Address |
17 | reti ;Output Compare0 Interrupt Vector Address |
18 | reti ; EEPROM Interrupt Vector Address |
19 | reti ; SPM complete Interrupt Vector Address |
20 | reti ; SPM complete Interrupt Vector Addres |
Ich sehe in der Zeile für den Overflow 0 Interrupt lediglich einen reti aber keine Weiterleitung zu einer Funktion ad 2)
1 | ldi temp1, 0x01 |
2 | out TIMSK, temp1 |
Die Schreibweise ist zwar besch..... weil man wissen muss, das Bit 0 in TIMSK den Overflow Interrupt freigibt, aber was solls. Der Timer 0 darf bei einem Overflow einen Interrupt generieren. ad 3) den sei seh ich im Code ad 4) Ich sehe aber keine Interrupt Funktion, die dem Vorbild des Tutorials folgt. Ich sehe aber sehr wohl einen in sehr weit gefassten Grenzen ähnlichen Programmteil, der über dubiose Pfade immer dann aufgerufen wird, wenn ein Zeichen empfangen wird. Das ist es aber nicht! Die Timer 0 Overflow Interrupt Funktion wird in regelmässigen Abständen vom Timer aufgerufen, unabhängig davon, ob über die UART ein Zeichen eintrudelt oder nicht! Die beiden Funktions- blöcke haben nichts miteinander zu tun (ausser dass die UART Empfangsfunktion ein empfangenes Byte in einem Register hinterlässt, welches von der Timer-PWM-Interrup Funktion ausgewertet wird).
womit ich jetzt nur auf dem Schlauch steh ist, dass ich ja 16 einzelne Kanäle hab die über dmx signal gesteuert werden. Ist überhaupt die verarbeitung des eingangssignals richtig. Im Anhang nur mal ein kleiner Schaltplan wie ich vor hab das ganze zu schalten. die 3. Leitungen ins leere sind die DMX-Eingänge. So gut soweit. Zurück zum Thema ich versteh nicht wie ich aus dem Interrupt in meine verschiedenen unterprogramme spring damit er mir z.b. kanal 7 anmacht und nicht alles!! oder legt man das mit dem register ocr fest?? wenn ocr als beispiel nur bei kanal 7 ungleich 0 ist so bleiben alle anderen kanäle aus aber durchlaufen wird trotzdem jeder kanal oder??? Sorry aber wie gesagt so richtig fit bin ich noch nicht aber durch dieses Projekt will ich mir ein wenig außerschulisches wissen aneignen! Deshalb ist mein Code auch ein wenig unübersichtlich bzw. lang oder umständlich. Ist mein erster Assemblercode den ich erstelle bzw. das erste vernünftige.
Joachim Geiger wrote: > Zurück zum Thema ich versteh nicht wie ich aus dem Interrupt in meine > verschiedenen unterprogramme spring damit er mir z.b. kanal 7 anmacht > und nicht alles!! oder legt man das mit dem register ocr fest?? wenn ocr > als beispiel nur bei kanal 7 ungleich 0 ist so bleiben alle anderen > kanäle aus aber durchlaufen wird trotzdem jeder kanal oder??? Ich kann dir nur raten: Nimm dir das Programm aus dem Tutorial und brenne es mal in deinen µC rein und spiele damit rum Es hat wenig Sinn da jetzt gross was dazu zu sagen, wenn du das Funktionsprinzip nicht verstehst. Und ehrlich gesagt weiss ich nicht, wie ich dir das noch einfacher erzählen kann. Von mir aus lade dir das Teil auch mal in den Simulator und geh mit Einzelschritten durch.
dann werd ichs mal so probieren. Nur noch eine Frage und zwar ich benötige dann ja 16 freie Register für den Code! -> Problem: soviele hab ich nicht mehr frei.
Lass die Interrupt Funktion zunächst mal so wie sie ist. AUf mehr Kanäle erweitern kannst du sie immer noch. PS: Die Einstellung der Helligkeiten der einzelnen LEDS geschieht nicht in der ISR. Die ISR realisiert lediglich die Helligkeitseinstellung. Aber gesetzt werden die Helligkeiten hier: ldi ocr_1, 0 ldi ocr_2, 1 ldi ocr_3, 10 ldi ocr_4, 20 ldi ocr_5, 80 ldi ocr_6, 127 Das setzt LED 1 auf aus (weil im Register ocr_1 eine 0 steht), LED 2 auf minimale Helligkeit (ocr_2 auf 1), LED 3 auf 'ein bischen heller' usw. bis zur LED 6 die auf volle Helligkeit gesetzt wird. Und wenn später irgendwann mal die LED 6 auf 'aus' gesetzt werden soll, dann lautet das ldi ocr_6, 0 und wenn du eine Zahl von der UART für die LED 3 hast, die deren Helligkeit darstellt, und diese Zahl möge sich in Register 25 befinden, so lautet das dann mov ocr_3, r25 Ansonsten brauchst du dich um nichts kümmern. Du schreibst einfach die gewünschten Zahlenwerte in die zugeordneten Register und die Interrupt Routine kümmert sich darum, dass die Led auch mit dieser Helligkeit leuchtet. Vielleicht ist es jetzt ein bischen klarer geworden.
Joachim Geiger wrote: > dann werd ichs mal so probieren. Nur noch eine Frage und zwar ich > benötige dann ja 16 freie Register für den Code! -> Problem: soviele hab > ich nicht mehr frei. Dann wirst du nicht umhin kommen ein paar SRAM Speicherzellen dafür abzustellen.
sorry wenn ich mich vielleicht falsch ausgedrückt hab oder so aber des hab ich soweit alles schon verstanden aber wie gesagt du hast da 6 register definiert und dann werte reingeladen. Sozusagen steht jedes register für die Helligkeit eines LEDs aber dann benötige ich ja 16 register. Des is halt mein Problem was ich hab. Deshalb komm ich nicht weiter. Die Register 1-15 kann ich nicht dazu nehmen oder?? Den Rest hab ich eigentlich soweit schon verstanden aber wie gesagt ich tu mich schwer mit der ausdrucksweise! Das Problem ist einfach auch dass ich ein grundgerüst des programms schon hatte und es "nur" erweitert hab und nicht von vorn herein komplett selbst durchdacht. Also wie gesagt ich versteh des schon aber mit den registern komm ich halt nicht klar weil ich nicht mehr so viele frei hab.
würde des funktionieren wenn ich anstatt den registern 16 speicherbytes dafür her nehm?????
Joachim Geiger wrote: > sorry wenn ich mich vielleicht falsch ausgedrückt hab oder so aber des > hab ich soweit alles schon verstanden aber wie gesagt du hast da 6 > register definiert und dann werte reingeladen. Sozusagen steht jedes > register für die Helligkeit eines LEDs aber dann benötige ich ja 16 > register. Exakt. Oder aber die Werte liegen nicht in Registern vor, sondern werden im SRAM gespeichert. Die Interrupt Funktion muss dann halt die Werte aus dem Speicher lesen anstatt sie schon in den jeweiligen Registern vorzufinden. Dafür können dann aber auch alle 16 Werte über ein einziges Register nacheinander abgewickelt werden. > Des is halt mein Problem was ich hab. Deshalb komm ich nicht > weiter. Die Register 1-15 kann ich nicht dazu nehmen oder?? Warum nicht? > Den Rest hab > ich eigentlich soweit schon verstanden aber wie gesagt ich tu mich > schwer mit der ausdrucksweise! Das Problem ist einfach auch dass ich ein > grundgerüst des programms schon hatte und es "nur" erweitert hab und > nicht von vorn herein komplett selbst durchdacht. Also wie gesagt ich > versteh des schon aber mit den registern komm ich halt nicht klar weil > ich nicht mehr so viele frei hab. Ganz ehrlich. Ich bin nicht Hannes. Solche Dinge programmiere ich in C. Dann brauch ich mich nicht darum zu kümmern wann welches Register welchen Inhalt hat. Ich lege einfach meine Variablen an, und der Compiler verteilt das dann im Speicher :-)
ich hab im tut wo gelesen dass die register 1-15 irgendwie schon belget sind bzw. wenn ich mein avr studio laufen lass dann schreibt er mir warnungen für die register aus wo kleiner wie 16 sind dass die schon verwendet worden sind. Müssen beim Arbeiten mit speicher die Pins PB... frei sein, also darf da nix dran hängen?? ich will doch nix raus geben sondern nur was intern speichern und bei bedarf wieder laden. Ich glaub ich steig jetzt auch mal wieder auf c um weil des mit den speichern und registern und was sonst noch alles is ziehmlich .....! Also find ich zumindest. Greif ich auf den RAM mit dem gleichen Prinzip wie wenn ich auf einen Flash rom oder eeprom zugreife??
Joachim Geiger wrote: > ich hab im tut wo gelesen dass die register 1-15 irgendwie schon belget > sind bzw. wenn ich mein avr studio laufen lass dann schreibt er mir > warnungen für die register aus wo kleiner wie 16 sind dass die schon > verwendet worden sind. Es gibt ein paar Einschränkungen für diese Register. Mann kann einige Operationen damit nicht machen. Aber ansonsten: In Assembler hast du die volle Kontrolle über die Register. Wenn du in r11 was hineinschreibst, dann hindert dich keiner daran. > > Müssen beim Arbeiten mit speicher die Pins PB... frei sein, also darf da > nix dran hängen?? ich will doch nix raus geben sondern nur was intern > speichern und bei bedarf wieder laden. > > Ich glaub ich steig jetzt auch mal wieder auf c um weil des mit den > speichern und registern und was sonst noch alles is ziehmlich .....! > Also find ich zumindest. > > Greif ich auf den RAM mit dem gleichen Prinzip wie wenn ich auf einen > Flash rom oder eeprom zugreife?? Du brauchst dazu die Befehle LDS, STS. Eventuell ist auch LDD bzw STD zusammen mit dem Z Register ein guter Weg. (Ich seh grade: dafür gibt es im Tutorial noch nicht mal ein Beispiel. Ts, ts. Nachlässig)
ok dann versuch ich mal weiter aber ich glaub ich nehm trotzdem die Speichermethode. Deshalb hab ich mir ja gedacht ich frag mal nach weil ich nix gefunden hab!!! Aber trotzdem ein mega Dankeschön!
Das sieht dann so aus (ungetestet)
1 | .include "m16def.inc" |
2 | |
3 | .def temp = r16 |
4 | .def temp2 = r17 |
5 | |
6 | .def PWMCount = r18 |
7 | |
8 | .org 0x0000 |
9 | rjmp main ; Reset Handler |
10 | .org OVF0addr |
11 | rjmp timer0_overflow ; Timer Overflow Handler |
12 | |
13 | main: |
14 | ldi temp, LOW(RAMEND) ; Stackpointer initialisieren |
15 | out SPL, temp |
16 | ldi temp, HIGH(RAMEND) |
17 | out SPH, temp |
18 | |
19 | ldi temp, 0xFF ; Port B auf Ausgang |
20 | out DDRB, temp |
21 | |
22 | ldi temp2, 0 |
23 | sts OCR_1, temp2 |
24 | ldi temp2, 1 |
25 | sts OCR_2, temp2 |
26 | ldi temp2, 10 |
27 | sts OCR_3, temp2 |
28 | ldi temp2, 20 |
29 | sts OCR_4, temp2 |
30 | ldi temp2, 80 |
31 | sts OCR_5, temp2 |
32 | ldi temp2, 127 |
33 | sts OCR_6, temp2 |
34 | |
35 | ldi temp, 0b00000001 ; CS00 setzen: Teiler 1 |
36 | out TCCR0, temp |
37 | |
38 | ldi temp, 0b00000001 ; TOIE0: Interrupt bei Timer Overflow |
39 | out TIMSK, temp |
40 | |
41 | sei |
42 | |
43 | loop: rjmp loop |
44 | |
45 | timer0_overflow: ; Timer 0 Overflow Handler |
46 | inc PWMCount ; den PWM Zähler von 0 bis |
47 | cpi PWMCount, 128 ; 127 zählen lassen |
48 | brne WorkPWM |
49 | clr PWMCount |
50 | |
51 | WorkPWM: |
52 | ldi temp, 0b11000000 ; 0 .. Led an, 1 .. Led aus |
53 | |
54 | lds temp2, OCR_1 |
55 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 1 erreicht |
56 | brlt OneOn |
57 | ori temp, $01 |
58 | |
59 | OneOn: lds temp2, OCR_2 |
60 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 2 erreicht |
61 | brlt TwoOn |
62 | ori temp, $02 |
63 | |
64 | TwoOn: lds temp2, OCR_3 |
65 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 3 erreicht |
66 | brlt ThreeOn |
67 | ori temp, $04 |
68 | |
69 | ThreeOn:lds temp2, OCR_4 |
70 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 4 erreicht |
71 | brlt FourOn |
72 | ori temp, $08 |
73 | |
74 | FourOn: lds temp2, OCR_5 |
75 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 5 erreicht |
76 | brlt FiveOn |
77 | ori temp, $10 |
78 | |
79 | FiveOn: lds temp2, OCR_6 |
80 | cp PWMCount, temp2 ; Ist der Grenzwert für Led 6 erreicht |
81 | brlt SetBits |
82 | ori temp, $20 |
83 | |
84 | SetBits: ; Die neue Bitbelegung am Port ausgeben |
85 | out PORTB, temp |
86 | |
87 | reti |
88 | |
89 | .DSEG ; das Folgende kommt ins SRAM |
90 | OCR_1: .BYTE 1 ; 6 Bytes für die OCR Register |
91 | OCR_2: .BYTE 1 |
92 | OCR_3: .BYTE 1 |
93 | OCR_4: .BYTE 1 |
94 | OCR_5: .BYTE 1 |
95 | OCR_6: .BYTE 1 |
Hallo Karl Heinz, cpi PWMCount, 128 ; 127 zählen lassen brne WorkPWM clr PWMCount geht das nicht eleganter? brcc WorkPWM clr PWMCount oder noch kürzer: andi PWMCount, 127 ; 127 zählen lassen Die Abfragereihe läßt sich auch als Schleife schreiben: ldi r30,byte0(OCR_6) ;Z zeigt auf Wert für LED6 ldi r31,byte1(OCR_6) ;weiß die genaue Syntax nicht ldi bitmuster,$20 ;mit LED6 (bit5) anfangen ldi temp, 0b11000000 ;0 .. Led an, 1 .. Led aus pwmloop: ld temp2,Z- ;Wert holen, Z für nächste LED vorbereiten cp PWMCount, temp2 ;ist der Grenzwert für Led erreicht? brne nichtsetzen or temp,bitmuster nichtsetzen: lsr bitmuster ;wirkt gleichzeitig als "Zähler" brne pwmloop ;wenn das Bit noch nicht "herausgefallen" ist out PORTB, temp ;Die neue Bitbelegung am Port ausgeben reti Nicht getestet.... Was hältst Du davon?
eProfi wrote: > Was hältst Du davon? Viele Wege führen nach Rom. > cpi PWMCount, 128 ; 127 zählen lassen > brne WorkPWM > clr PWMCount > > geht das nicht eleganter? > > oder noch kürzer: > andi PWMCount, 127 ; 127 zählen lassen In dem konkreten Fall würde das selbstverständlich gehen. Und jetzt mach mal 100 Stufen :-) > Die Abfragereihe läßt sich auch als Schleife schreiben: Yep. Ich hab trotzdem Loop Unrolling gemacht, weil: * Im Tutorial der Zugriff aufs SRAM überhaupt noch nicht ghezeigt wurde * Und daher klarerweise der Zugriff über den Z-Pointer plus Offset auch noch unbekannt sind. Wäre aber eine gute Gelegenheit, dieses Thema zum Anlass zu nehmen, diese Dinge in das Tutorial mit einzubauen.
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.