Forum: Mikrocontroller und Digitale Elektronik PWM mit µC klappt nicht


von nachtbastler (Gast)


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!

von nachtbastler (Gast)


Lesenswert?

Ich meine natürlich, dass die LED an PortD.0 hängt! Kleiner Tippfehler.

von nachtbastler (Gast)


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

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

nachtbastler schrieb:
> Nach meinen Überlegungen müsste die Blinkfrequenz aber unsichtbar sein!
> Erkennt vielleicht jemand den Fehler?

 2MHz = 500ns
 500ns * 60000 = 30ms
 30ms * 2 = 60ms

 Wieso soll 16.6Hz unsichtbar sein ?

: Bearbeitet durch User
von nachtbastler (Gast)


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.

von Marc V. (Firma: Vescomp) (logarithmus)


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.

: Bearbeitet durch User
von nachtbastler (Gast)


Lesenswert?

Habe ich doch?
Const Timer1preload = 60000

und später

Timer1 = Timer1preload

von nachtbastler (Gast)


Lesenswert?

Ach so, das gilt nur ein einziges Mal während der Initialisierung des 
Programmes?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

nachtbastler schrieb:
> Timer1 = Timer1preload

 Ja, einmal am Anfang.
 Sobald dein Timer bis 0 abgezählt hat, springt der in die ISR und
 fängt dort aber wieder von Null an.

von nachtbastler (Gast)


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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

nachtbastler schrieb:
> Jetzt funktioniert es! Vielen Dank.

 Was ist das für ein Basic überhaupt ?

von nachtbastler (Gast)


Lesenswert?

AVR-Bascom.
Geflasht wird aber mit myAVR-Progtool, finde ich praktischer und 
funktioniert einwandfrei.

von Peter D. (peda)


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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter Dannegger schrieb:
> 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.

 Wahrscheinlich kann man Timer1 auch so betreiben, vllt sogar direkt
 PWM, etwa:
 Config Timer1 = Timer, [Counter], [CTC (oder PWM ) ? ]

: Bearbeitet durch User
von nachtbastler (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

nachtbastler schrieb:
> Welchen Vorteil hat es, das Clear aus dem Interrupt rauszuhalten?

Weil die Hardware dann das alles selbsttätig macht.
Und zwar auf den Taktzklus genau. Und zwar auch dann, wenn sich die 
Abarbeitung der ISR verzögert, weil gerade eine andere ISR ihr Ding 
macht.

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
Noch kein Account? Hier anmelden.