Hallo zusammen, ich möchte OCR1A beschreiben uint8_t WertL, WertH; uint16_t Wert; =>>> Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; <=== OCR1A = Wert; Ich vermute, OCR1A wird nicht richtig beschrieben. So funzt es: OCR1AH = WertH; OCR1AL = WertL; Ist obige Zeile =>>> Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; <=== richtig überlegt ? Ich fürchte nicht ...! Danke im voraus
Hendrik L. schrieb: > So funzt es: > > OCR1AH = WertH; > OCR1AL = WertL; Dann lass es doch einfach so. Wenn du OCR1A beschreibst, wird der Compiler sowieso deine gerade so kunstvoll zusammengerechneten Bytes wieder auftrennen und daraus genau das machen, was die obigen beiden Zeilen tun. > Ist obige Zeile > > =>>> Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; <=== > > richtig überlegt ? Ich fürchte nicht ...! Sieht aber eigentlich gut aus.
Mit diesem Problem kämpfe ich nun 2 Tage (dachte immer ich hätte die PWM Modi nicht verstanden). Offensichtlich liegt das Problem aber in dieser Zuweisung. Ich versuche zu verstehen. Danke für die Antwort.
Die 16-Bit-Register kannst du ganz normal beschreiben z.b.
1 | OCR1A = 4242; |
Wenn du willst oder es praktischer ist kann du auch getrennt nach Low und High-Byte schreiben. Ich schreibe eigentlich nur explizit das Low-Byte wenn das High-Byte nicht genutzt wird z.b. wenn Timer1 im 8-Bit Mode läuft. Vielleicht liegt der Fehler ja auch wo anders, poste doch mal deinen ganzen Code. Gruß Matthias
weitere Details: Ich verwende im ATTiny 2313 FastPWM (Mode 14) mit ICR1 auf 20.000 gesetzt (Entsprechende PWM Frequenz wird am DIGI-Oszilloskop erkannt - stimmt mit vorausberechneter PWM Frequenz auf 0.5% überein!) Aber der Duty Cycle lässt sich hinsichtlich OCR1B nicht verstellen, wohl aber vollumfänglich bei OCR1A ! Bei OCR1B wird lediglich der berühmte Spike (bei TOP+1 timer cycle) sichtbar. Für die Experten: //----------------- if (xxxx == 114) f8: 80 91 71 00 lds r24, 0x0071 fc: 82 37 cpi r24, 0x72 ; 114 fe: 49 f4 brne .+18 ; 0x112 <__stack+0x33> { cli (); 100: f8 94 cli OCR1B = Wert; 102: 80 91 69 00 lds r24, 0x0069 106: 90 91 6a 00 lds r25, 0x006A 10a: 99 bd out 0x29, r25 ; 41 10c: 88 bd out 0x28, r24 ; 40 sei(); 10e: 78 94 sei 110: 10 c0 rjmp .+32 ; 0x132 <__stack+0x53> TCCR1A &= ~(1 << COM1B1); } */ } //.......................................................... else if (xxxx == 103) 112: 87 36 cpi r24, 0x67 ; 103 114: 49 f4 brne .+18 ; 0x128 <__stack+0x49> { cli(); 116: f8 94 cli OCR1AH = WertH; 118: 80 91 61 00 lds r24, 0x0061 11c: 8b bd out 0x2b, r24 ; 43 OCR1AL = WertL; 11e: 80 91 66 00 lds r24, 0x0066 122: 8a bd out 0x2a, r24 ; 42 sei(); 124: 78 94 sei 126: 05 c0 rjmp .+10 ; 0x132 <__stack+0x53> TCCR1A &= ~(1 << COM1A1); } //--------------------- Der Abfragezweig xxxx == 114 funzt NICHT! hinsichtlich PWM (offensichtlich unveränderbarem OCR1B - Wert) xxxx == 103 FUNZT! hinsichtlich PWM (Vermutung richtiger OCR1A - Wert) Vertausche ich nun OCR1B und OCR1A in obigem Code - dann jeweils die andere PWM falsch, hat also definitiv nix mit A oder B zu tun. OC1A und OC1B sind disconnected - Ports werden in Interrupt Routinen ISR(TIMER1_COMPA_vect) ISR(TIMER1_COMPB_vect) und ISR(TIMER1_OVF_vect) "von Hand" auf HIGH oder LOW gesetzt. ???? Bin völlig ratlos !!!!
>Für die Experten:
Die "Experten" hätten gerne vollständigen, möglichst compilierbaren
Quellcode. Keine von Dir redigierten Schnippsel die in der Regel eines
nicht zeigen: Die Ursache des Problems. :-)
Das ist die Bedeutung der Auffordernung: "... poste doch mal deinen
ganzen Code."
Hmm schrieb: >>Für die Experten: > > Die "Experten" hätten gerne vollständigen, möglichst compilierbaren > Quellcode. Keine von Dir redigierten Schnippsel die in der Regel eines > nicht zeigen: Die Ursache des Problems. :-) > > Das ist die Bedeutung der Auffordernung: "... poste doch mal deinen > ganzen Code." Danke für Deinen freundlichen Hinweis! Obiger Code reicht aber völlig aus! Die Logik in meiner Argumentation ist ja recht einfach wie schlüssig: Wenn ich zu Fuss die HByte ond LByte von OCRx beschreibe, funktioniert der PWM Mode 14 wie erwartet. Beschreibe ich das 16 Bit Register OCRx direkt, geht's nicht. Vertausche ich OCR1A und OCR1B in obigem Beispiel, dann funzt die jeweilige andere PWM (oder eben nicht). Beschreibe ich beide OCR1x mit 16bit direkt, funzen beide PWMs nicht. Beschreibe ich beide getrennt, mit LOW und HIGH-Byte, dann funzen beide PWMs. Nun könnte ich sagen, das Problem ist gelöst -aber bislang habe ich verstanden, dass man nur in ASM auf die getrennte Register-Beschreibung zu achen hat, bei C sollte der Compiler den Programmierer sorglos stellen. Dennoch, danke für Deine Zeit!
Da ist ein Widerspruch in Deiner Argumentation: Du weisst nicht was das Problem ist, aber weisst, welche Information relevant ist. Umgekehrt wird es richtiger sein: Du verwirfst eine Information die, entgegen Deiner Einschätzung eben doch relevant ist. Es im Moment nicht möglich zu sagen, wo genau die Ursache liegt. Am besten ist es soviel Informationen wie möglich zu geben. Aber Informationen auszuwählen und nur die zu posten welche Du als notwendig erachtest, steht im Widerspruch zu der Tatsache das Du nicht in der Lage bist, die nur in Deinem Besitz befindliche Gesamtheit der Informationen so zu deuten, das Du Dein Problem alleine lösen kannst. Die Lösung wird aber eben ein Detail dieser Gesamtheit sein, dessen Bedeutung Du falsch einschätzt. Das ist nun weder ungewöhnlich noch setzt es Dich herab. Das passiert den Besten und mir und Dir erst recht. Um es zusammenzufassen: Unter den Informationen, die Du verwirfst und hier nicht postest ist genau die, welche das Problem löst. Sei also so gut und poste alle Informationen. Und wenn Du mir einen persönlichen Gefallen tun willst, dann benutze nicht dieses unsägliche "funzen". Da kräuseln sich mir die Fussnägel.
Hendrik L. schrieb: > Obiger Code reicht aber völlig aus! Nö, denn da ist kein Fehler drin, also muss er woanders sein. Wo ist z.B. der Code, der 'Wert' "zusammenbastelt". Und ich meine nicht das, was im ersten Post steht, denn das ist vermutlich was "Eingetipptes". Ich meine den realen Code (per Copy&Paste).
Stefan Ernst schrieb: > Hendrik L. schrieb: >> Obiger Code reicht aber völlig aus! > > Nö, denn da ist kein Fehler drin, also muss er woanders sein. > > Wo ist z.B. der Code, der 'Wert' "zusammenbastelt". Und ich meine nicht > das, was im ersten Post steht, denn das ist vermutlich was > "Eingetipptes". Ich meine den realen Code (per Copy&Paste). wurde oben schon beschrieben: //------------------------------- uint8_t WertL, WertH; uint16_t Wert; =>>> Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; <=== //-------------------------------- WertL und WertH werden über I2C "gefüllt". Kontroll-Lesen über I2C ergibt, dass WertL und WertH mit den richtigen Bytes gefüllt worden sind, um der Berechnung nach den gewünschten Wert an OCR1x zu übergeben! zu können Für den 8bit Timer OCR0A funzt die I2C Mimik einwandfrei - ebenso für OCR1B UND OCR1A wenn wie oben beschrieben mit Bytes gearbeitet wird. An den I2C Routinen liegt es also auch nicht. Gruß
Hallo Hendrik L. ohne jetzt alles haarklein durchzugehen, vielleicht hilft dir das weiter: http://www.mikrocontroller.net/articles/AVR_16-Bit-Register Gruß!
Fabian O. schrieb: > Nutzt Du AVR Studio 5? Dann kann es ein Fehler des Compilers sein. Version 4.19 Built 730!
Hendrik L. schrieb: > wurde oben schon beschrieben: > //------------------------------- > uint8_t WertL, WertH; > uint16_t Wert; > > =>>> Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; <=== > > //-------------------------------- Und ich hatte extra dazu geschrieben, dass ich DAS nicht nochmal sehen will, sondern den ECHTEN Code per Copy&Paste.
Vertausche mal die Zeilen, die High und Low zuweisen. Eventuell ist die Reihenfolge wichtig, weil der Wert gepuffert wird. Sowas sollte aber im Datenblatt stehen.
Bla schrieb: > Vertausche mal die Zeilen, die High und Low zuweisen. Eventuell ist die > Reihenfolge wichtig, weil der Wert gepuffert wird. Sowas sollte aber im > Datenblatt stehen. Danke für den Hinweis! Es ist aber so, dass die Einzelzuweisung ja funktioniert - die Reihenfolge ist also richtig. Was nicht funktioniert, ist die 16-bit Zuweisung, die der Compiler automatisch erstellt. Darum habe ich ja die vom Compiler generierten ASM-Zeilen angehängt- weil ich mich in ASM nicht so gut auskenne. Also, wenn ich die Anweisungen entsprechend Datenblatt "zu Fuss" in C programmiere, funzt es. Nur heisst es in den Tutorials auch, dass GNU-C die 16-bit Zuweisung in Maschinencode selbst (richtig) erzeugt. Dennoch Danke für Deine Hilfe. Gruß
Also, das Problem liegt definitiv in der Umrechnung durch diese Zeile Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; 120: f3 2e mov r15, r19 122: ee 24 eor r14, r14 124: c7 01 movw r24, r14 126: 82 0f add r24, r18 128: 91 1d adc r25, r1 Habe zwischenzeitlich mit union und structure 16 bit und 8 Byte HIGH und LOW aufeinander gemapped - und schon funzt die direkte 16 bit Zuweisung auf OCRx1. Gute Nacht!
Hendrik L. schrieb: > Habe zwischenzeitlich mit union und structure 16 bit und 8 Byte HIGH und > LOW aufeinander gemapped - und schon funzt die direkte 16 bit Zuweisung > auf OCRx1. das nennt man den Teufel mit dem Beelzebub austreiben
Hendrik L. schrieb: > Also, > > das Problem liegt definitiv in der Umrechnung durch diese Zeile > > Wert = (uint16_t) WertH * 256 + (uint16_t) WertL; > 120: f3 2e mov r15, r19 > 122: ee 24 eor r14, r14 > 124: c7 01 movw r24, r14 > 126: 82 0f add r24, r18 > 128: 91 1d adc r25, r1 Was stimmt daran nicht?
Das ist meine ursprüngliche und immer noch aktuelle Frage! Wobei mein Programm jetzt funktioniert, indem ich diese Berechnung durch ein Speichermapping ersetze (2 Byte auf Word). Das ist erst einmal das wichtigste nach stundenlangem Frust. Vielen Dank an Alle, die mitüberlegt haben. Gruss
lbd schrieb: > Das ist meine ursprüngliche und immer noch aktuelle Frage! wenn Du ein Problem hast und möchtest das jemand dir hilft, dann solltest du ihm die Informationen zur Verfügung stellen um die er dich bittet. Du behauptest dass du weißt wo das Problem liegt und wirfst den Leuten irgendwelche Häppchen zu in denen es liegen soll. Entweder musst du deine Probleme allein lösen oder du hilfst denen die dir helfen sollen.
Walter S. schrieb: > lbd schrieb: >> Das ist meine ursprüngliche und immer noch aktuelle Frage! > > wenn Du ein Problem hast und möchtest das jemand dir hilft, dann > solltest du ihm die Informationen zur Verfügung stellen um die er dich > bittet. > > Du behauptest dass du weißt wo das Problem liegt und wirfst den Leuten > irgendwelche Häppchen zu in denen es liegen soll. > > Entweder musst du deine Probleme allein lösen oder du hilfst denen die > dir helfen sollen. Ich bin da gänzlich anderer Meinung! Offensichtlich gibt es mit obiger Berechnung ein Problem, ersetze ich die Zeile, ist das Problem weg. Es ist zwar unbefriedigend, nicht zu wissen, warum - aber für mich ist der Weg nicht (immer) das Ziel. (Interessant ist, dass auf den ersten Blick die obige Zeile als korrekt empfunden wird - von mir, wie auch anderen). Im übrigen habe ich die Zeile sowohl im MAIN als auch in Interrupt Routinen plaziert - immer das gleiche, es funzte nicht - egal wo im gesamten Code die Berechnung eingefügt wurde. Umgekehrt funzt es jetzt, wenn man LOW und HIGH Byte erst einzeln zuweist, die auf eine 16bit Strukur (WORD) mappt und dann dieses WORD den Register ICRx1 zuweist. Grundsätzlich funzt also eine 16-bit Register Zuweisung bei OCRx1 in GNU C! Ist doch gut zu wissen - für diejenigen, die auch evtl. einmal in ein solches Problem reinlaufen. Also noch einmal Danke für die Anregungen und Hilfen! Noch einen schönen Ostermontag wüscht Hendrik.
Hendrik L. schrieb: > Offensichtlich gibt es mit obiger Berechnung ein Problem, ersetze ich > die Zeile, ist das Problem weg. Und schon wieder eine voreilige Schlussfolgerung. Nein, es gibt kein Problem mit der Berechnung. Das Problem ist immer noch irgendwo anders (z.B. Register werden vorher oder nachher irgendwie korrumpiert). Und ein Ersetzen der Zeile durch was anderes entfernt nicht das Problem, sondern kaschiert es nur.
Ich würde mal eine neuere Compilerversion probieren, wenn Du es wirklich auf die eine Zeile eingrenzen kannst. Siehe hier: Beitrag "Umwandlung von zwei uint8_t in uint16_t erzeugt falschen Code?"
Das Umstellen des Code kaschiert den Fehler nur, es beseitigt ihn nicht. Er wird Dir daher bei nächster Gelgenheit wieder auf die Füße fallen. Wenn Du den fehlerhaften Code partout nicht zeigen willst, Dein Bier. Deine Annahmen kannst Du Dir sämtlichst sparen, die bringen niemanden was.
Wenn du den Code nicht öffentlich machen willst, bau doch einfach mal ein Minimal-Beispiel. Vereinfache dein Programm so weit, dass es nur noch den Fehler produziert und nichts weiter. Da sollten ja ein paar Zeilen reichen. Wichtig ist, dass es fertig kompilierbarer Quelltext ist. Die Assembler-Zeilen sind ok... sofern der korrekte Wert im korrekten Register steht.
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.