Zu PWM-Duty=0: das ist normal bzw folgt aus der Auswertung des OutputCompareMatches. Du verwendetest den Mega88 oder so, dazu mal
Datenblatt 15.5 - Output compare unit(Seite92) schrieb:
Whenever TCNT0 equals OCR0A or OCR0B, the comparator signals a match. A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle.
Als WGM hatten wir einen single slope mode gewählt, bei dem der Timer beim OCR0A-CompareMatch überläuft. Dort ist der zusätzliche "next" Timertakt bereits abgezogen (siehe meine Formel). Beim Tiny10 kommt da 207 raus (208-1), der Timer läuft also bis 207, wodurch das match signalisiert wird, aber erst im nächsten Takt wirksam wird. Im 208ten Takt wird der Timer also dann (wie gewünscht) 0.
Wenn Du also für KanalB 'ne 0 vorgibst, geht der Pin im Überlauf Hi, und erst im nächsten Timertakt wieder low (durch unseren Prescaler entspricht das einem Systemtakt).
Also muß ich hier auch immer 1 abziehen? Ja - aber für 0 wäre das ja TOP (also OCR0A), dann fällt das match-event aber mit dem Überlauf zusammen (und wird ignoriert) - das Hi-setzen des OC-Beinchens beim Überlauf erfolgt aber.
Wie kannst Du das umgehen? Indem Du das ganze invertierst - also nicht die an-Zeit, sondern die aus-Zeit festlegst. Dann erreichst Du zwar nicht mehr die volle Leistung, die brauchst Du hier aber auch nicht, oder? Für volle Leistung und komplett abschalten können könnte man zB für die empfangene 0 den CompareOutputMode abschalten (und für jede andere Zahl an). Dann geht Dir natürlich der Fall 1 (0 senden für einen Takt Hi-Pegel) verloren.
Zum OSCCAL: man könnte zB ein Programm schreiben, welches OSCCAL gesteuert beschreibt, und irgendwie ausgibt. Mit dem Tiny10 habe ich weniger Möglichkeiten. man könnte zB 2 Taster (entprellt) verwenden, die OSCCAL inkremetieren/dekrementieren. Ein Timer läuft im Hintergrund (da unabhängig vom Programm), und toggelt automatisch den ComparePin (also auch Hardware im Hintergrund). Bei einem 8bit-Timer sollte so also ein 512stel der CPU-Frequenz messbar sein. Damit kannst Du OSCCAL erstmal abgleichen. Die Ausgabe kann entweder über eine gelatchte serielle Kommunikation erfolgen, oder man gibt es in Form von 8 LEDs binär aus, oder man legt den Wert im Eeprom ab, oder...
Beim Tiny10 hab ich aber nur 3 I/Os und keinen Eeprom... aber ich könnte das fast Direkt mit meinem Programm machen - Der DutyCycle von KanalB wird mit 103 (ca 50%) fetsgelegt, nach empfang eines Bytes schreibe ich dieses nach OSCCAL. Dann sollte sich Die PWM-Frequenz ändern, deren Sollwert ich ja kenne/vorgegeben habe. Dummerweise werde ich mit höchster Wahrscheinlichkeit aber erstmal dermaßen daneben liegen, daß mein taktgebundener serieller Empfang unbrauchbar(*) wird, und ich resetten muß. (Start, LA-Trigger starten, Terminalprogramm senden, Frequenz ansehen, Reset, LA-Trigger starten, ...)
(*) man könnte natürlich aus der neuen PWM-Frequenz die neue (sicher krumme) Baudrate des Controllers ermitteln (war ja (8fach-Oversampling) das 8fache der Bitfrequenz=Baudrate) und versuchen, diese dem Terminalprogramm vorzgeben. Das geht aber auch nicht schneller, als den Controller zu resetten.
Beachte, daß die Kalibration auch von Temperatur und Versorgungsspannung abhängt (also die Oscillatorfrequenz, aber daraus folgend natürlich auch Deine Kalibration).
Hmm... eine hab ich noch: ich könnte ja erstmal den voreingestellten Wert von OSCCAL retten, nach dem Empfang (= Trigger) schreibe ich OSCCAL für ein paar Überläufe um, danach wird OSCCAL wiederhergestellt. Dadurch sollte die veränderte Frequenz auswertbar sein, mein UART aber trotzdem wieder (halbwegs) stimmen.