PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AtMega32 PWM 1x 16Bit



Dominik009
18.08.2013, 19:01
Hallo,

Ich möchte gerne an meiner RnControll am Mega32 pwm mit 16 Bit laufen lassen.
Timer 1 ist ja ein 16 Bit timmer daher sollte das ja auch funktionieren.

Nur leider kann ich beim pwm konfigurieren max. 10 Bit bei Timer 1 einsetzen, bei 11 und höher meldet bascom avr einen Fehler.

Wir kann ich das hinbekommen? Am besten ein kurzes Beispiel, wie ich pwm mit 16bit über Timer 1 konfiguriere, da ich noch nicht ganz so viel Ahnung habe.

Gruß
Dominik

Sauerbruch
18.08.2013, 19:57
Hallo Dominik,

auch das ist ein Beispiel dafür, dass das Programmieren von PWM-Anwendungen mit Bascom manchmal etwas limitiert ist. Ob die neuesten Versionen die Möglichkeit bieten, PWM auch mit einer Breite von mehr als 10 Bit zu konfigurieren, weiß ich nicht. Die einfachste Möglichkeit, die eigentlich auch immer funktionieren sollte, ist die, die beiden relevanten Register selber zu setzen (TCCR1A und TCCR1B).

Wenn Du Dir mal die Tabelle im Datenblatt auf Seite 109 anschaust, siehst Du, dass es insgesamt 16 PWM-Modi gibt, die mit den Bits WGM13, WGM12, WGM11 und WGM10 ausgewählt werden können.

Was Bascom Dir anbietet sind die Modi 1, 2 und 3: Der Zähler zählt bis zu einem Maximalwert (TOP genannt) von 0x00FF (=255 d.h. 8 Bit), 0x01FF (=511 d.h. 9 Bit) oder 0x02FF (=1023 d.h. 10 Bit). Das ist sozusagen eine "quick-and-dirty"-Lösung, bei der man den oberen Grenzwert nicht extra ein Register schreiben muss.

Der Modus 10 bietet genau das gleiche (PWM, Phase correct), der maximale Zählerwert ist aber über das Register ICR1 definiert. Wenn Du in dieses Register den maximal möglichen Wert 65535 schreibst, zählt der Counter bis zu diesem Wert hoch, d.h. Du hast ein echtes 16-Bit PWM.

Weil das Register ICR1 aus zwei Bytes besteht ist es wichtig zu wissen, dass man unbedingt erst das höhere Byte beschreiben muss! Also
ICR1H = 255
ICR1L = 255

Schau Dir die beiden Register TCCR1A und TCCR1B im Datenblatt doch mal an, mit denen kannst Du das Verhalten der beiden Ausgangspins OC1A und OC1B, den PWM-Modus und den Prescaler festlegen.

Kampi
18.08.2013, 20:00
Hey,

ich denke das hier sollte dir helfen:

http://www.mikrocontroller.net/topic/305895

Bascom kennt anscheinend keine 16-Bit PWM.
Du musst das also händisch machen:

https://www.roboternetz.de/community/threads/40279-16-Bit-PWm-mit-ATMega-32

for_ro
18.08.2013, 20:05
Hallo Dominik,
schau dir mal die Tabelle der Modi von Timer1 im Datenblatt des M32 auf S. 109 an. Die Modi 1-3 kannst du in Bascom direkt über den Config Timer1 Befehl erzeugen. Um 16-bit Auflösung zu bekommen, musst du die anderen PWM Modi verwenden.
Dazu setzt du die Bits WGM13..0 in den Registern TCCR1A und B entsprechend der Werte in der Tabelle.
Wenn ICR1 als Top Wert in der Tabelle steht, kannst du über ihn den Max Wert setzen und über Compare1A (OCR1A) und Compare1B (OCR1B) die Duty Cycle.
Wenn OCR1A als Top Wert angegeben ist, setzt du ihn auf den max-Wert und OCR1B auf den Umschaltpunkt.
Also z.B. Mode 8:
TCCR1B.WGM13=1
TCCR1B.WGM12=0
TCCR1A.WGM11=0
TCCR1A.WGM10=0
ICR1=65535
OCR1A = 6553
16 bit Auflösung, 10 DC.
Frequenz ergibt sich dann aus _XTAL/Prescale/65536

Dominik009
18.08.2013, 20:28
Vielen dank für die Hilfe, das Forum hier ist wirklich Super!

Also den kann ich's.b. Modus 8 oder Modus 10 benutzen.
stelle ich den mit dem letzen Code hier von for_ro nur Timer 1 ein oder auch andere?

Das ich mit wgm10-13 den timermodus einstellen kann hab ich jetzt verstanden. Das mit icr1 hab ich auch verstanden, nur das mit ocr1a hab ich nicht verstanden. Bei Modus 8 und 10 brauche ich den doch garnicht, oder?
Und was genau ist Duty Cycle?

Viele Grüße und nochmal vielen dank für eure mühe
Dominik

Kampi
18.08.2013, 20:40
Der Code ist nur für Timer1. Für andere Timer hast du andere Registeradressen.
Der Duty Cycle ist das Puls-Pausen Verhältnis der PWM:

http://de.wikipedia.org/wiki/Tastgrad

Der Timer1 hat 2 PWM Kanäle bzw. Ausgänge, Pin 18 D4 -> OC1B und Pin 19 D5 -> OC1A.
Mit den Registern ocr1a und ocr1b stellst du die PWM der beiden Pins ein.
Du hast als einen Timer mit zwei (!) unabhängigen PWM Modulen.

Dominik009
18.08.2013, 22:12
Also ist Duty Cycle eigentlich der PWM wert den ich dann einstelle?

Es funktioniert leider nicht so toll. Ich möchte Timer 1 auf Modus 10 Schalten (der ist ja gleich zum normalen Modus von Timer 1 bei PWM).

Daher hab ich folgendes eingestellt:




$regfile = "m32def.dat" $framesize = 32 $swstack = 32 $hwstack = 32 $crystal = 16000000 $baud = 9600
Config Pind.4 = Output
Config Pind.5 = Output

Config Timer1 = Pwm
TCCR1B.WGM13=1
TCCR1B.WGM12=0
TCCR1A.WGM11=1
TCCR1A.WGM10=0
ICR1H= 65535
ICR1L = 65535
OCR1A = 10000

Do

Pwm1a = 10000
wait 1
Pwm1a = 20000
wait 1
Pwm1a = 30000
wait 1
Pwm1a = 40000
wait 1
Pwm1a = 50000
wait 1
Pwm1a = 60000
wait 1

loop

End



Es funktioniert nicht und ich bekomme in der Zeile " TCCR1B.WGM13=1 " immer 2 Fehler. Wenn ich Sie lösche sind die selben fehlermeldungen in der nächsten Zeile.

Ich hoffe ihr könnt mir helfen, ich bin nämlich langsam am verzeweifeln.

Gruß Dominik

for_ro
18.08.2013, 22:27
Leider wieder so eine kleine Gemeinheit der Bascom Entwickler. Die Bits heißen beim M32 im Dat-File anders:
;TCCR1A
COM1A1 =7
COM1A0 =6
COM1B1 =5
COM1B0 =4
FOC1A =3
FOC1B =2
PWM11 =1 '=WGM11
PWM10 =0 '=WGM10

;TCCR1B
ICNC1 =7
ICES1 =6
CTC11 =4 '=WGM13
CTC10 =3 '=WGM12
CTC1 =3 ; Obsolete - Included for backward compatibility
CS12 =2
CS11 =1
CS10 =0

Oder du definierst die dir selber:
Const WGM13 = 4 '4 ist hier wieder die Bitnummer im Register TCCR1B
Const WGM12 = 3
Const WGM11 = 1
Const WGM10 = 0

Du kannst auch direkt ICR1 setzen:
ICR1=65535

ICR1H und L sind Byte Werte, denen kannst du auch nur bis 255 zuweisen.
PWM1A ist dasselbe wie OCR1A

Kampi
19.08.2013, 06:14
Also ist Duty Cycle eigentlich der PWM wert den ich dann einstelle?



Genau.
Bei einer PULSWEITENmodulation änderst du (wie der Name es schon sagt ;) ) die Pulsweite, sprich das Puls-Pausen Verhältnis.
Dadurch ergeben sich unterschiedliche Effektivwerte der Spannung.
Und wie for_ro es schon gesagt hat, der Mega32 ist ein 8-Bit Mikrocontroller, d.h. alle Register sind in der Regel 8-Bit groß.
Bei manchen Funktionen werden bestimmte Register zu einem "Paket" zusammen gefasst (wie es bei ICR1 der Fall ist, oder beim Timer1 Zählregister). Beschrieben werden die Register dann trotzdem in zwei Schritten, von daher macht es kaum einen Unterschied ob du nun den 16-Bit Wert in das Paket schreibst oder beide Register einzeln (klar könnte man sagen, dass du nur das Low Register ändern musst wenn du den Wert änderst und nicht das komplette Register....aber das sollte für dich erst mal egal sein).
Einen Integerwert kannst du dann so aufteilen (Bascom Hilfe....Funktionen High() und Low()):



Dim I As Integer , Z As Byte
I = &H1001
Z = High(i) ' is 10 hex or 16 decEnd

Dominik009
19.08.2013, 10:19
Danke für eure Hilfe, leider funktioniert es immer noch nicht.
Könnt ihr mir vieleicht sagen was ich falsch mache, oder den code korrigieren? Ein Fehler wird bei "ICR1=65535
" angezeigt. Wenn ich es in ICR1H und ICR1L aufteile hab ich den fehler nicht, aber ich hab keine Ahnung wie ich die einzeln Zuweise. Ich kan so ja max. 255 zuweisen, da es 2 8-Bit Werte sind, aber ich brauch ja 65535.

Ich glaube generell das der Code eh ziemlich falsch ist, vieleicht könntet ihr ja mal drüberschauen. Ich verzweifel nämlich langsam!





$regfile = "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 16000000
$baud = 9600
Const WGM13 = 4 '4 ist hier wieder die Bitnummer im Register TCCR1B
Const WGM12 = 3
Const WGM11 = 1
Const WGM10 = 0
Config Pind.4 = Output
Config Pind.5 = Output
Config Timer1 = Pwm
TCCR1B.WGM13=1
TCCR1B.WGM12=0
TCCR1A.WGM11=1
TCCR1A.WGM10=0
ICR1= 65535

Do
Pwm1a = 10000
wait 1
Pwm1a = 20000
wait 1
Pwm1a = 30000
wait 1
Pwm1a = 40000
wait 1
Pwm1a = 50000
wait 1
Pwm1a = 60000
wait 1

loop

End


Ich hoffe ihr könnt mir weiterhelfen

Viele Grüße
Dominik

for_ro
19.08.2013, 10:30
Hallo Dominik,
das Setzen von ICR 1 sollte eigentlich funktionieren, evtl. steht die Adresse des Registers nicht im Dat-File des M32.
Wenn du es mit separaten H und L machst und auf 65535 kommen willst, dann so wie Sauerbruch es oben geschrieben hat.

Dein Timer läuft noch nicht, weil du keinen Prescale angegeben hast.
Wenn du Ausgänge schalten willst, musst du dies auch konfigurieren, etwa so:
Config Timer1 = PWM, Prescale = 1, Compare_A_PWM = Clear_Up

Dominik009
19.08.2013, 10:37
Morgen Fo_Ro,

danke für die Hilfe, werde gleich noch "Config Timer1 = PWM, Prescale = 1, Compare_A_PWM = Clear_Up" in den COnde mit reinmachen. Dann sollte alles soweit stimmen, oder?

Wie komme ich den von ICR1H = 255 und ICR1L = 255 auf meine 65535? Werden einfach beide 8 Bit Werte multipliziert?

Also wenn ich die Zeile mit Config Timer 1.... noch einsetze und anstellte von ICR1 einfach ICR1H und ICR1L sollte es funktionieren, oder gibt es sonst noch fehler?

Gruß Dominik

Kampi
19.08.2013, 10:57
Hey,

um aus zwei 8 Bit Werten einen 16-Bit Wert zu machen, reicht es die aneinander zu hängen:

1111 1111 1111 1111

So kommst du auf deinen Wert.
Ebenso geht es mit dem Teilen....einfach nach 8 Bit einen Cut machen und die Werte unter High und Low speichern

for_ro
19.08.2013, 11:18
Also wenn ich die Zeile mit Config Timer 1.... noch einsetze und anstellte von ICR1 einfach ICR1H und ICR1L sollte es funktionieren, oder gibt es sonst noch fehler?

Sonst scheint es mir ok zu sein.
Du hast im Code den Pin D.4 (OC1B) als Ausgang definiert, so als wolltest du dort auch ein Signal bekommen. Wenn dem so ist, musst du auch noch die Option Compare_B_PWM angeben und entsprechende Werte für PWM1B setzen.

Dominik009
19.08.2013, 19:04
Vielen Dank an euch alle für eure hilfe. Es läuft momentan alles 1a! Danke sehr!

Gruß Dominik