PWM mit µC klappt nicht

Gast #3869039
Lesenswert?

Hallo,

folgender Quellcode:
1
$regfile "m8def.dat"
2
$crystal = 2000000
3

4
Config Portd.0 = Output
5
Const Timer1preload = 60000
6
Config Timer1 = Timer , Prescale = 1
7

8
Enable Timer1
9
Timer1 = Timer1preload
10

11
On Timer1 Feuer
12

13
Enable Interrupts
14

15
Do
16
Loop
17

18
Feuer:
19
Toggle Portd.0
20
Return
Eigentlich ganz simpel.
Leider blinkt die LED deutlich sichtbar.
Nach meinen Überlegungen müsste die Blinkfrequenz aber unsichtbar sein!
Ich betreibe die LED (Low-Current-LED) über einen 1K-Widerstand direkt 
am PortD.1.
Der ATmega funktioniert aber, denn wenn ich die LED mit waitms in der 
do-loop-Schleife im Abstand von 1 ms toggle, dann bleibt sie dauerhaft 
an und gedimmt?!

Fusebits habe ich richtig gesetzt, ich nutze den internen Oszillator auf 
2 MHz. Die gesetzten Werte sind E2 für Low und D9 für High.

Erkennt vielleicht jemand den Fehler?
Vielen Dank!
Gast #3869042
Lesenswert?

Mit Timer0 funktioniert die ganze Schose übrigens wunderbar.
1
$regfile "m8def.dat"
2
$crystal = 2000000
3

4
Config Portd.0 = Output
5
Const Timer0preload = 250
6
Config Timer0 = Timer , Prescale = 1
7

8
Enable Timer0
9
Timer0 = Timer0preload
10

11
On Timer0 T0_ir
12

13
Enable Interrupts
14

15
Do
16
Loop
17

18
T0_ir:
19
Toggle Portd.0
20
Return
Gast #3869051
Lesenswert?

Preload heißt doch, dass der Timer erst bei diesem Wert zu zählen 
anfängt.
Bis zum Überlauf beim Timer1 dauert es also noch ca. 5000 Takte. Ein 
Takt hat 0,5µs, also haben 5000 davon 2,5 ms.

Die LED schaltet also alle 5 ms, ergibt eine Taktrate von 200 Hz. Das 
sehe ich nicht mehr als sichtbar an.
Deswegen wundert es mich, dass dem so ist.
(Firma: Vescomp) #3869057
Lesenswert?

nachtbastler schrieb:
> Die LED schaltet also alle 5 ms, ergibt eine Taktrate von 200 Hz. Das
> sehe ich nicht mehr als sichtbar an.
> Deswegen wundert es mich, dass dem so ist.
 Ja, dann ist es eben noch schlimmer:
 2MHz = 500ns
 500ns * 65536 = 32.768ms
 32.768ms * 2 = 65.536ms

 LOL.
 Wie wäre es, wenn du in deiner ISR den Timer1 wieder mit 60000 lädst ?
 Etwa so:
1
Feuer:
2
  Toggle Portd.0
3
  Timer1=60000
4
  Return

 Ansonsten fängt der arme Timer immer mit 0 an.
Gast #3869063
Lesenswert?

Jetzt funktioniert es! Vielen Dank.

Ich dachte, dass ich mit den oben genannten Anweisungen dem Timer 
bereits gesagt hätte, dass er jedes Mal bei Wert X starten soll. Aber 
wenn das natürlich nur ein einziges Mal gilt kann das natürlich nichts 
werden.
#3869254
Lesenswert?

nachtbastler schrieb:
> Ich dachte, dass ich mit den oben genannten Anweisungen dem Timer
> bereits gesagt hätte, dass er jedes Mal bei Wert X starten soll.

Dem Timer ist völlig wurscht, ob Du eine Variable "Timer1preload" 
nennst. Du kannst sie auch "Blub" nennen.
Er macht nur das, was im Code steht.

Wenn man mal ins Datenblatt schaut, sieht man aber, daß T1 einen 
Clear-On-Compare Mode kann. Dann muß man das Clear nicht jedesmal im 
Interrupt-Code machen.
Gast #3869817
Lesenswert?

Welchen Vorteil hat es, das Clear aus dem Interrupt rauszuhalten?
Das wird ja nur ein Problem, wenn die Zeit zwischen zwei Interrupts 
nicht ausreicht, um den Code im Interrupt auszuführen, oder?

In diesem Fall wäre das relativ unwahrscheinlich, da nur eine LED 
getoggelt werden soll. Ansonsten gebe ich dir aber natürlich recht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren