PWM & Timer ISR mit einem Counter?

OP #3786514
Hallo zusammen,

ginbt es beim tiny44 eine Mgl, mit dem Timer0 einen IR auszulösen und 
gleichzeitig eine im dutycycle einstellbare PWM zu realisieren?

In welchem Mode muss man dazu den Timer0 betreiben? Einfach von 0...255 
laufen lassen, damit die ISR aufrufen und mit einem CTC Vergleich einen 
Pin setzen?

Danke, Klaus.
(Firma: matzetronics) #3786674
Klaus R. schrieb:
> In welchem Mode muss man dazu den Timer0 betreiben? Einfach von 0...255
> laufen lassen, damit die ISR aufrufen und mit einem CTC Vergleich einen
> Pin setzen?

Du kannst sowohl 'Phase Correct' als auch 'Fast PWM' Modi nutzen und den 
Overflow Interrupt nutzen, um das gewünschte OCR Register mit deinem 
neuen PWM Wert zu schreiben. Ein CTC ist dazu nicht nötig.
Neben der PWM Frequenz ist der Unterschied zwischen den beiden PWM Modi, 
das der TOV Interrupt bei Fast PWM bei TOP gesetzt wird und bei Phase 
Correct ist BOTTOM der Auslöser.
Gast #3786930
Hallo Matthias,

heißt, ich könnte den timer auch ab 55 loslaufen lassen, hätte dann 200 
"incremente", iregndwo auf den wert zwischen 55...255 setze ich den 
compare. beim compare lösche ich den entspr pin, beim overflow setze ich 
ihn wieder UND incrementiere meine interne zählvariable, die mir als 
zeitbasis dient - korrekt?

Danke, Klaus.
Gast #3786953
Hi

>heißt, ich könnte den timer auch ab 55 loslaufen lassen, hätte dann 200
>"incremente", iregndwo auf den wert zwischen 55...255 setze ich den
>compare. beim compare lösche ich den entspr pin, beim overflow setze ich
>ihn wieder UND incrementiere meine interne zählvariable, die mir als
>zeitbasis dient - korrekt?

Der korrekte Weg wäre Timer-Mode7 mit TCR0A als Top. Du lädst OCR0A mit 
199 und benutzt OCR0B mit 0..199 für die PWM.

MfG Spess
OP #3787425
Hallo Spess,

mit...

ISR (TIM0_COMPA_vect) {          // Timer 0

  timebase_superslow++;
  timebase_slow++;
  timebase_fast++;
  if(delay)delay--;
  PORTA ^= (1 << LED_B);
  }

TCCR0A = (1<<WGM01) | (1<<WGM00) | (0<<COM0A1) | (0<<COM0A0) | 
(1<<COM0B1) | (1<<COM0B0);
TCCR0B |= (1<<WGM02) |(1<<CS02)|(0<<CS01)|(1<<CS00);

GIMSK |= (1<<INT0)|(0<<PCIE1)|(0<<PCIE0);
MCUCR |= (1<<SM1)|(0<<SM0)|(1<<ISC01)|(0<<ISC00);

TIMSK0 |= (1<<TOIE0) | (1<<OCIE0A) | (1<<OCIE0B);

OCR0A = timer;
OCR0B = PWM;

sei();

...macht zwar der PWM Pin OC0B exakt was er soll, die LED_B in der ISR 
toggelt jedoch nicht alle x ms, sondern geht nur für atemberaubende 
480us an (ISR wird also 2x aufgerufen, das erste Mal exakt 60us nach dem 
CompareB event) - ich gehe davon aus, dass der Compare Interrupt nur bei 
TCNT0 = OCR0A ausgelöst wird, also EINMAL pro Zähler-Zyklus?

Was hab ich übersehen? Der main-code ist komplett auskommentiert, es 
läuft nur die ISR.

Klaus.
OP #3787509
...restlichen beiden?

OCR0B setzt direkt den Pin, da läsuft die PWM ja auch. Aus OCR0A wollte 
ich nur eine ISR abzweigen, um die internen Zählvariablen zu 
inkrementen...die gibt es also nicht. INT0 dient nur zum Zählen von 
Flanken, das funktionierte auch einwandfeei (bis ich den T0 statt mit 
Signal Overflow auf Timer & PWM umgebaut habe)...

ISR (INT0_vect) {   // Einsprung (nach Ende sleep_mode) durch INT0

off_count++;

}

EDIT: Falls du die PWM ISR meinst, die gibt es (noch) nicht, die PWM 
läuft derzeit mit Fix-werten.
Gast #3787532
Klaus R. schrieb:
> TIMSK0 |= (1<<TOIE0) | (1<<OCIE0A) | (1<<OCIE0B);
>
> OCR0A = timer;
> OCR0B = PWM;
>
> sei();

Compare 0B Interrupt ist aber auch enabled. Wenn da keine ISR existiert, 
gibts einen Reset? oder sonst was. Entweder ISR deklarieren oder den 
OCIE0B nicht enablen.
OP #3787587
...einen Reset? Hoppa. Das wäre ggf eine Erklärung.

Laut Datenblatt nahm ich an, dass das I-Bit gesetzt wird, aber dann auch 
wieder gelöscht wird. Und fertig. Ich kann für COMP_B ja mal eine 
Dummy-ISR anlegen.

Klaus.
Gast #3787603
Hi

>Laut Datenblatt nahm ich an, dass das I-Bit gesetzt wird, aber dann auch
>wieder gelöscht wird. Und fertig.

Die Stelle aus der du das heraus gelesen haben willst möchte ich mal 
sehen. Das I-Bit wird durch einen ausgeführten Interrupt oder durch 
Schreiben einer Eins ins I-Bit gelöscht.

>Ich kann für COMP_B ja mal eine Dummy-ISR anlegen.

Dann fehlt immer noch die Overflow-ISR. Einfacher wäre es die 
Interruptfreigaben zu löschen.

MfG Spess
#3787621
Klaus R. schrieb:
> ...einen Reset? Hoppa. Das wäre ggf eine Erklärung.
>
> Laut Datenblatt nahm ich an

Zuständig ist hier nicht das Prozessor Datenblatt sondern die Compiler 
Doku (ich nehm mal an wir reden vom GCC).

Alle freigegebenen Interrupts, für die keine ISR existiert, werden zu 
einer Standard-ISR geroutet, welche - tata - einen Programm Neustart in 
die Wege leitet.

Man gibt niemals einen Interrupt frei, für den man keine ISR hat!
Oder man jubelt der Runtime eine Default-ISR unter, die nichts tut.
Tut man keines von beiden, dann kriegt man eben Programm-Neustarts 
sobald die Interrupt Situation auftritt.
OP #3787650
...verrückt, diese Compiler :) Ist aber sehr plausibel.

Danke, ich werde berichten!

EDIT: Wie gil ist das denn bitte - das wars! Diese &%$§*# ISR Routine 
hat mich echt vor ein Rästel gestellt - wieder was gelernt.

D-A-N-K-E Karl-Heinz!
OP #3787812
...ja, ich schon wieder :)

Ich habe von Karl-Heinz schon einen Beitrag dazu gefunden

Beitrag "OCR1A lässt sich nur 1x ändern"

aber auch ich habe noch das Problem, dass OCR0B nur den initialen Wert 
von OCR0B_Load einmal übernimmt und sich von

ISR (TIM0_COMPB_vect) {          // Timer0 - PWM Reload

  void WriteOCR0B(){

  OCR0B = OCR0B_Load;

  }

nicht sonderlich beeindrucken lässt...?!

Klaus.
Gast #3787829
Hi

>ISR (TIM0_COMPB_vect) {          // Timer0 - PWM Reload

>  void WriteOCR0B(){

>  OCR0B = OCR0B_Load;

>  }

Kannst du mir, als notorischen Assemblerprogrammierer, mal erläutern, 
was du damit bezweckst.  Sieht irgendwie schräg aus.

MfG Spess
OP #3787853
Hi Spess,

es gibt eine "Lichtfunktion", in der aus einem lookup eine PWM Kennlinie 
in der main in OCROB_Load geschrieben wird. Wenn die ISR aufgerufen 
wird, soll das der nächste Compare Wert sein und das Licht langsam über 
die Kennlinie hochdimmen.

Das void... kann ich mir schenken, klar. Aber guck dir mal den Link an, 
oben :) Laut DB wird das Register beim compare nachgeladen...also, so 
wie ich das verstehe.

Klaus.
OP #3787912
...volatile unsigned int?

Und wir in der main mit den "lesbaren" PWM Werten aus dem Array 
berechnet:

OCR0B_Load = ((100-LED_W_PWM)*2-1);

...und nein, auch mit Werten <100 funktioniert es nicht (die gefährliche 
-1 fällt mir grad auf)

Klaus.
Gast #3787943
Beim den PWM-Modes der AVR-Timer werden übrigens OCRnx nur zu 
definierten, für den Ablauf ungefährlichen Zeitpunkten von sichtbaren 
Register in die wirklich benutzten Schattenregister übernommen. Ein 
setzen zu einem bestimmten Zeitpunkt (per ISR) ist also garnicht 
notwendig. Einfach jederzeit reinschreiben, die HW synchronisiert das 
dann zur laufenden PWM.
OP #3787950
Weiß ich, alles schon gelesen - aber selbst wenn ich in der main stumpf

OCR0B_Load = ((100-LED_W_PWM)*2);

schreibe, scheint das nur beim "Start" zu gehen, dann übernimmt er nix 
mehr.

Aber ich teste es nochmal genauer...kann also eigentlich nicht sein?

Klaus.



EDIT:

Nix...nur Dunkelheit - änder ich die Werte per Hand, macht die PWM, was 
sie soll:

  LED_W_PWM = LED_W_PWM + 1;

    OCR0B_Load = ((100-LED_W_PWM)*2);

vs.

OCRB_Load = 5; (aber da weiß ich nicht, ob das halt nur einmal 
ausgeführt wird, wenn der Interrupt initialisiert wird)

EDIT2: ...nope, er nimmt den Wert nur genau einmal direkt nach dem Init 
der Register. Dann (in der while(1) Essig...man man.

EDIT3: OK, Fixwerte, also "einfache Zahlen" werden übernommen - aber 
keine Variableninhalte. Müssen die VAR speziell initialisiert sein o.ä.? 
Ist volatile unsigned int niO?

Klaus.
#3787991
> EDIT3: OK, Fixwerte, also "einfache Zahlen" werden übernommen - aber
> keine Variableninhalte.

Quatsch

Die Syntax ist
1
    Ziel = Ausdruck;
wie der der Teil 'Ausdruck' zusammengesetzt ist, spielt keine Rolle. 
'Ausdruck' kommt mit einem Zahlenwert hoch, egal wie kompliziert der 
Ausdruck aufgebaut ist. Und dieses Ergebnis wird an das Ziel zugewiesen.

Dein job ist es, dafür zu sorgen, dass der Wert, der aus 'Ausdruck' 
resultiert auch der Wert ist, den du haben willst. Aber wie 'Ausdruck' 
aufgebaut ist, ob Konstante oder arithmetischer Ausdruck, ob mit oder 
ohne Variablen, ob durch Funktionsaufrufe zusammengesetzt oder nicht, 
spielt keine Rolle. Resultierender Wert ist resultierender Wert. Wir 
sind doch hier nicht bei BASCOM.
OP #3789077
Was ist denn BASCOM? :)

Letzte Frage: Wieso bleibt bei OCR0A = 0 ein Puls von 130us überig? Den 
sieht man :( [Naja, man kann sich wunderschön die DIE-Struktur der LED 
und den fleckigen Phosphor und die Bonddrähte ansehen] - wenn ich OCR0A 
= 100 setze, geht er jedoch auf volle 100%?

Klaus.
OP #3789339
Aha! ...dachte ich es mir, amn sieht es im Diagramm des DB.

FAQ

Wieso geht die LED nie ganz aus?
    Es ist normal, dass die LED selbst bei OCR1A = 0 immer noch ganz 
schwach leuchtet. Die Hardware-PWM funktioniert so, dass bei einem 
Timerwert von 0 auf jeden Fall der Ausgang eingeschaltet wird. Danach 
kommt der Compare Match bei 0 und schaltet gleich wieder aus. Daher ist 
der Ausgang für einen PWM-Takt eingeschaltet. Um das zu ändern, muss man 
entweder invertierte PWM nutzen, dann ist allerdings der Ausgang nie zu 
100% High, sondern hat immer einen Takt Low beim maximalem PWM-Wert. 
Oder man schaltet bei 0 einfach die PWM-Funktion ab und und setzt den 
Ausgang normal auf Low. [1].

Klaus.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.