Guten Tag, an meinem ATMega16 haben ich einen Ausgang, den ich über einen Variableninhalt steuern möchte. Wenn der Variableninhalt z.B. 0xFF ist, so soll der Ausgang dauerhaft an sein. Bei einem 0x00 dauerhaft aus und bei einem 0x80 dementsprechend ca. 50% an. Ich habe keine Idee wie ich die ISR gestalten müsste, damit ich dieses Resultat erhalte. Hat da jemand eine Lösung für?
ist noch ein Timer frei? welche Frequenz soll es werden? Was für eine ISR meinst du?
Ich habe noch alle Timer frei. Bei der Frequenz habe ich so an 1kHz gedacht.
klingt nach einer Hausaufgabe. Deine ISR wird regelmäßig aufgerufen (Frequenz darfst du dir ausrechnen). In der ISR zählst du eine Veriable hoch. Entspricht sie deinem Grenzwert, schaltest du den Ausgang um. Irgendwann hat die Variable den oberen Grenzwert (Überlauf...) erreicht, dann schaltest du den Ausgang wieder. Vorher noch die Abfrage, ob der Sollwert einem deiner beiden Grenzwerte entspricht, und entsprechend den Ausgang schalten.
Georg M. schrieb: > Tim schrieb: >> Ich habe noch alle Timer frei. > > Und warum soll das dann Pseudo-PWM sein? Naja, "Pseudo-PWM" ist es ja sowieso nicht, auch eine in Software realisierte PWM-Lösung ist natürlich einfach nur PWM und nix anderes. Software PWM kann durchaus sinnvoll sein. Immer dann, wenn man viele PWM-Kanäle braucht. Und natürlich insbesondere dann, wenn man mehr PWM-Kanäle braucht, als die verfügbaren Timer anzubieten haben. Oder aber auch, wenn man eine höhere Auflsung braucht, als die verfügbaren Timer anzubieten haben.
STK500-Besitzer schrieb: > klingt nach einer Hausaufgabe. find ich auch, daher gibts weitere Tipps auch nur auf Nachfrage wenn ein Grundkozept steht. Zwei Fragen hätte ich aber noch. Welche Sprache solls denn werden, und soll es eine Fast PWM (nur hochzählen) oder eine Phase Correct PWM (hoch und runterzählen) werden? c-hater schrieb: > Software PWM kann durchaus sinnvoll sein. auf nem Mega16 mit allen Timern unbenutzt und nur 8 bit eher nicht wirklich, klingt zu sehr nach Hausaufgabe. Oder Anfänger mit halbfertigem Ansatz, dann bitte das wirkliche Problem schildern (was soll die PWM tun, wer ändert wann den Wert usw.) und nicht den gewählten Lösungsweg. Dann gibt es sehr viel Aussagekräftigere Hilfe.
:
Bearbeitet durch User
K. S. schrieb: > auf nem Mega16 mit allen Timern unbenutzt und nur 8 bit eher nicht > wirklich Naja, der Kracher ist der Mega16 mit maximal 4 PWM-Kälen in Hardware (davon nur zwei in 16Bit-Auflösung) ja nun auch nicht wirklich. Da könnte durchaus mal der Wunsch nach einer Software-PWM aufpoppen... > klingt zu sehr nach Hausaufgabe. Wäre durchaus möglich. Aber ich habe ihm ja auch keinen Code geliefert, er muss sie also immer noch alleine erledigen ;o)
Hausaufgabe? Okay. Wie putzig :) Ich habe mir tatsächlich auch schon etwas überlegt, aber das macht meiner Meinung nach eher weniger Sinn, weshalb ich auf das posten verzichtet hatte.
1 | volatile uint8_t percent = 40 * 255 / 100; // => 40% an, 60% aus |
2 | ISR(TIMER0_OVF_vect) |
3 | { |
4 | static uint8_t cnt = 0; |
5 | |
6 | if(cnt >= percent) PORTA &= ~(1 << PA7); |
7 | else PORTA |= (1 << PA7); |
8 | |
9 | cnt++; |
10 | } |
Mir gefällt an dieser Lösung aber nicht, dass im jedem Aufruf auch die Bedingung überprüft wird. Gibt es dafür eine elegantere Lösung?
Tim schrieb: > Mir gefällt an dieser Lösung aber nicht, dass im jedem Aufruf auch die > Bedingung überprüft wird. Gibt es dafür eine elegantere Lösung? Die Bedingung zu überprüfen würde mich weniger stören, als jedes mal den Port zu updaten. Ausserdem musst du noch einen Spezialfall (entweder Dauer-low oder Dauer-high) behandeln. Vorschlag:
1 | volatile uint8_t pwm_duty = 102; // 40% an, 60% aus |
2 | |
3 | ISR(TIMER0_OVF_vect) |
4 | { |
5 | static uint8_t cnt = 0; |
6 | |
7 | if (cnt == 0) |
8 | { |
9 | if (pwm_duty > 0) |
10 | PORTA |= (1 << PA7); // low->high |
11 | else |
12 | PORTA &= ~(1 << PA7); // stay low |
13 | } |
14 | else if (cnt == pwm_duty) |
15 | PORTA &= ~(1 << PA7); // high->low |
16 | |
17 | cnt++; |
18 | } |
Tim schrieb: > Mir gefällt an dieser Lösung aber nicht, dass im jedem Aufruf auch die > Bedingung überprüft wird. Gibt es dafür eine elegantere Lösung? Etliche. Praktisch alle davon wurden bereits hier oder in "Projekte und Code" gezeigt. Das Grundprinzip bleibt allerdings immer das Gleiche. Die verschiedenen Implementierungen unterscheiden sich nur darin, an welcher Stelle die Bedingung geprüft wird und wie deutlich das für einen Programmier-Laien noch erkennbar ist, dass da irgendwo was geprüft wird. Die Prüfung an sich ist aber völlig unverzichtbar. Das liegt in der Natur des Problems...
Tim schrieb: > Mir gefällt an dieser Lösung aber nicht, dass im jedem Aufruf auch die > Bedingung überprüft wird. Gibt es dafür eine elegantere Lösung? naja, für nur einen 1 Kanal PWM nur bedingt: - du nimmst einen Timer mit Overflow sowie Compare Match Interrupt, in einem setzt du den Ausgang, im anderen löscht du den Ausgang wieder. ist dann aber eine Hardware PWM mit Umwegen. Vorteil ist es funktioniert auch mit mehreren PWM Kanälen, Beispiel weiter unten hier: https://www.mikrocontroller.net/articles/Soft-PWM - du lässt es so wie es ist, der Overhead um die ISR funktion auzurufen ist wahrscheinlich eh länger als die ISR selber. - Du speicherst bei Änderung der PWM 256 Werte in einem Array, und schiebst die dann in der ISR nur raus, ist aber Aufwendiger und ineffizienter als Testen. Weiterhin musst du die Aktualisierung dieses Arrays synchronisieren, sonst bekommst du Glitches (und wenn du alle interrupts währenddessen einfach anhältst kannst du auch Glitches bekommen) c-hater schrieb: > Die Prüfung an sich ist aber völlig unverzichtbar. Das liegt in der > Natur des Problems... da kommst du nicht drum rum bei 1kHz PWM und 8bit brauchst du einen entsprechend oft aufgerufenen Interrupt, da bleibt echt kaum Zeit übrig. Rechne mal selber nach, vergiss nicht die Zyklen für JMP/RETI und Register sichern, das wird schon eng. Guck mal in die Listing Files vom GCC (wenn du den Verwendest), dann siehst du wie lang die ISR wirklich ist. Daher würde ich zu dem Ansatz mit Timer raten.
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.