Forum: Mikrocontroller und Digitale Elektronik Atmega16 PWM konfigurieren bei 8MHz und bei 16MHz CPU-Takt


von Sebastian W. (code)


Lesenswert?

Hallo ich bräuchte Hilfe beim Thema PWM!

Ich habe einen Atmega16 mit 8 MHz getaktet und in Bascom folgende PWM 
eingestellt:

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Prescale = 1 
, Clear_timer = 1


So funktionierts einwandfrei. Ich gebe mit dem Atmega16 an einem 
Lautsprecher eine 8KHz WAV Datei aus.

Jetzt möchte ich aber vom CPU-Takt auf 16 MHz wechseln.
Leider passt die PWM jetzt nicht mehr. Gibt es eine Möglichkeit die PWM 
auf
die gleiche Geschwindigkeit wie bei 8 MHz CPU-Takt zu bekommen?

mfg
Sebastian

von holger (Gast)


Lesenswert?

Prescale = 2?

von Sebastian W. (code)


Lesenswert?

Das wäre ja schön wenns ginge. Der nächste Prescaler ist aber 8.

von holger (Gast)


Lesenswert?

>Das wäre ja schön wenns ginge. Der nächste Prescaler ist aber 8.

Ich weiss;)

Du brauchst zwei Timer. Timer1 für die Samplerate
und Timer2 für die PWM.

von Sebastian W. (code)


Lesenswert?

Das hab ich. Die Samplerate ist auch nicht mein Problem.
Den Timer für die Samplerate hab ich angepasst. Der läuft genau so 
schnell wie bei 8 MHz Takt. Die PWM passt aber nicht

von RonnyRoster (Gast)


Lesenswert?

wie schnell muss denn deinen PWM laufen? Bzw welches problem gibt es, 
wenn sie schneller ist?
Du musst doch einfach bei jedem Sample deine PWM neu einstellen und die 
sollte dann für die Gültigkeit des Samples mindestens eine volle Periode 
durchlaufen. Du hast bei 16MHz Takt und 8kHz Samplerate aber etwa 8 PWM 
Perioden für jedes Sample.

von holger (Gast)


Lesenswert?

>Das hab ich. Die Samplerate ist auch nicht mein Problem.
>Den Timer für die Samplerate hab ich angepasst. Der läuft genau so
>schnell wie bei 8 MHz Takt. Die PWM passt aber nicht

Das seh ich in deinem BASCOM Code leider nicht.

Timer1 stellst du auf CTC mit der Samplerate.
Timer2 auf Fast PWM.

Wie das mit BASCOM geht weiss ich nicht.

von Sebastian W. (code)


Lesenswert?

Hier der komplette Source.
Die LookupTable pcm habe ich aber gekürzt. Da hängen ca. 12000 Werte 
drin.
Das Programm spielt eine 8KHz Wav ab. Mit diesem Source und 8MHz 
funktionierts.


$regfile = "m16adef.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 10
$framesize = 40

Dim Empfangen As Byte

Config Timer0 = Timer , Prescale = 1
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Prescale = 1 
, Clear_timer = 1

Dim I As Word
Dim Sample_count As Byte

On Timer0 Isr_von_timer1
Enable Interrupts
Disable Timer0

Sample_count = 4

Config Portd.5 = Output

Ocr1a = 0
I = 0





Do
   Wait 1
   Enable Timer0
Loop


Isr_von_timer1:
Sample_count = Sample_count - 1

If Sample_count = 0 Then
   Sample_count = 4
   I = I + 1

   Empfangen = Lookup(i , Pcm)
   Ocr1a = Empfangen

   If I = 12405 Then
      I = 0
      Disable Timer0
   End If
End If

Return



Pcm:
Data 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 
16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 
, 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 
45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 
, 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 
74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 
, 89 , 90 , 91 , 92 , 93 , 94 , 95 , 96 , 97 , 98 , 99,
Data 100 , 101 , 102 , 103 , 104 , 105 , 106 , 107 , 108 , 109 , 110 , 
111 , 112 , 113 , 114 , 115 , 116 , 117 , 118 , 119 , 120 , 121 , 122 , 
123 , 124 , 125 , 126 , 127 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128,
Data 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128,
Data 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128,
Data 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 
128 , 128 , 128 , 128 , 128,
...

von Karl H. (kbuchegg)


Lesenswert?

Wenn dein µC doppelt so schnell läuft, kannst du dann nicht hier

   Ocr1a = Empfangen

ganz einfach immer das doppelte des Wertes nach OCR1A laden?

Der Timer zählt doppelt so schnell, allerdings doppelt so weit. Unterm 
Strich braucht er dann wieder genauso lang.


Edit:
Config Timer1 = Pwm , Pwm = 8

Allerdings brauchst du dann auch eine 9 Bit PWM

von RonnyRoster (Gast)


Lesenswert?

Ich kenne mich mit Bascom nicht aus aber mir scheint, dass du immer nach 
4 mal timer0 eine neue PWM setzt(ich steig da garnicht durch aber evtl 
reicht dir, bis 8 zu zählen...).
Ziel ist es aber, alle 1/8000s einen neuen PWM-Wert zu setzen.
Also nimmst du deinen Sample-Timer setzt ihn auf Prescaler 8 und ins 
Output Compare Register schreist du 250. Dann hast du einen 8kHz 
Interrupt (bei 16MHz. Im Timer setzt du dann den PWM wert neu.

Wenn du es noch schicker machen willst, dann liest du die Lookup Table 
im Main aus, speicherst den nächsten Wert in einer Variable, und setzt 
dann im Timer Interrupt nur schnell die PWM neu, dazu noch eine 
Variable, die der main-Schleife bescheid sagt, dass es den nächsten Wert 
aus der Tabelle lesen muss.

Den PWM Timer ansich stellst auf Prescaler 1 und PWM Mode.

von Sebastian W. (code)


Lesenswert?

Hallo RonnyRoster,

ja das mit dem 4x Zählen ist nicht sauber.
Ist auch ein Beispiel das ich aus dem Netz hab. Ich werd das noch 
optimieren. Hab den Zähler natürlich bei 16 MHz auf 8 gestellt.
Ging auch nicht.

ABER! Ich hab den Fehler gefunden.
Ich Depp betreibe einen Atmega16L mit 16 MHz.
Der kann ja eigentlich nur 8 MHz. Funktioniert zwar trotzdem aber mit 
Fehlern. Hab die Versorgungsspannung von 5V auf 4,5V gestellt und 
plötzlich funktionierts einwandfrei :-)
Ich wechsle dann doch mal auf einen Atmega16A

Vielen Dank aber für die Hilfe!

mfg
Sebastian

von Klaus D. (kolisson)


Lesenswert?

RonnyRoster schrieb:
> Ich kenne mich mit Bascom nicht aus aber mir scheint

Das musste ich jetzt zitieren weil es Spass machte.

Lieber Autor: Sebastian Weidmann (code) ,
im Gegensatz zu vielen Usern hier, liebe ich Bascom und ich kenne
deine Problematik. Ich hab mir schon tagelang den "Wolf" gesucht
als ein Timer nicht wie geplant funktionierte.

Ich kann nur empfehlen , von den "config timer" Geschichten
Abstand zu nehmen und stattdessen direkt zu adressieren.
z.B.
TCCR1A = &B01000100

oder sowas.
Dann klappt das auch


Gruss Klaus

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.