Hi leute,
ich brauchte PWM und da ich mich noch nicht so gut damit auskannte, hab
ich erst mal nen paar tut's gelesen und ne Funktion für den Allgemeinen
gebrauch geschrieben. Klappt auch alles super nur kommt mir die funktion
nen bisschen aufgebläht vor und da dachte ich mir, vllt könnte mir
jemand nen paar Tipps geben um die Funktion zu verkleinern?
Die Funktion ist im anhang.
Danke schonmal ;)
Gruß Robin
edit: seh gerade hab beim if/else "prescaler" einmal noch 64 statt 1024,
kleiner copy/past fehler halt ;)
// hier ggf. eine Fehlerbehandlung für ungültige Parameter einbauen
34
break;
35
}
36
37
if(fast)
38
{
39
TCCR1A|=(1<<WGM12);
40
}
41
42
switch(prescaler)
43
{
44
case0;
45
TCCR1B|=(1<<CS10);
46
break;
47
case8:
48
TCCR1B|=(1<<CS11);
49
break;
50
case64:
51
TCCR1B|=(1<<CS11)|(1<<CS10);
52
break;
53
case256:
54
TCCR1B|=(1<<CS12);
55
break;
56
case1024:
57
TCCR1B|=(1<<CS12)|(1<<CS10);
58
break;
59
default:
60
// hier ggf. eine Fehlerbehandlung für ungültige Parameter einbauen
61
break;
62
}
63
}
Der Code sollte nach diff-vergleich äquivalent sein. Falls du Lust hast,
das mal zu kompilieren, würde mich der Codeumfang im Vergleich
interessieren.
Grüße
Stefan
Robin Gerhartz schrieb:> @holger: Wie gehts denn besser?
Indem du auch die jeweils relevanten Bits auf 0 setzt und nicht nur
diejenigen auf 1, die du brauchst.
Oder auf Deutsch: Du hast da eine Annahme getroffen. Nämlich die, das
die anderen Bits automatisch 0 sind. Zb. beim Prescaler. Ist als
Prescaler 8 angegeben, dann setzt du CS11. Aber was ist mit den anderen
Bits? In einer allgemein verwendbaren Funktion darfst du nicht davon
ausgehen, dass diese automatisch 0 wären. Was ist wenn du die Funktion 2
mal mit verschiedenen Prescalern aufrufst? Passiert dann immer noch das
richtige?
1
switch(prescaler)
2
{
3
...
4
5
6
case8:
7
TCCR1B&=~((1<<CS12)|(1<<CS10));
8
TCCR1B|=(1<<CS11);
9
break;
10
11
....
jetzt tut es das.
Auch so
1
TCCR1B&=~((1<<CS12)|(1<<CS11)(1<<CS10));
2
3
switch(prescaler)
4
{
5
...
6
7
8
case8:
9
TCCR1B|=(1<<CS11);
10
break;
11
12
....
tut es das, ohne das du dich bei den Einzelfällen damit abquälen musst.
Wenn man einmal weiter denkt, dann wäre es vernünftig
* die 2. Variante zu benutzen
* das Rücksetzen der Prescaler Bits ganz am Anfang der Funktion zu
machen.
Denn: Wenn der Timer bereits läuft und eine PWM generiert, dann ist
nicht vorhersehbar was passieren wird, wenn man dem bereits laufenden
Timer die PWM während des Betriebs umkonfiguriert.
Also
1
voidOCR1_PWM(booleanB,
2
booleaninverted,
3
booleanfast,
4
uint8_tbit,
5
uint16_tprescaler,
6
uint16_tvalue)
7
{
8
TCCR1B&=~((1<<CS12)|(1<<CS11)(1<<CS10));
9
10
....
So ist sicher gestellt, dass
* die Bits auf jeden Fall 0 sind
* der Timer angehalten ist, so dass man relativ gefahrlos die
PWM Einstellung ändern darf.
Gut hab die Bits vorher mal alle zurück gesetzt.
Und mir is noch auf gefallen das ich den Bit WGM12 im falschen Register
setzen wollte, wurde auch korrigiert. Es braucht im folgendem Beispiel
laut AVRDude auf dem µc 502bytes.
So hab auch mal für die beiden anderen Timer auf dem Atmega328p ne
Funktion geschrieben und default überall "8Bit" oder "ohne Prescaler"
eingestellt.
Meine frage jetzt sind die so in Ordnung oder sollte ich noch was
verändern?
Bespiel:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
// #include <m328p/OCR0.c>
4
// #include <m328p/OCR1.c>
5
#include<m328p/OCR2.c>
6
7
intmain(void){
8
inti;
9
while(1){
10
for(i=10;i<=70;i+=2){
11
OCR2_PWM(0,0,1,32,i);
12
_delay_ms(33);
13
}
14
for(i=70;i>=10;i-=2){
15
OCR2_PWM(0,0,1,32,i);
16
_delay_ms(33);
17
}
18
}
19
return0;
20
}
OCR0 - avrdude: 398 bytes of flash verified
OCR1 - avrdude: 498 bytes of flash verified
OCR2 - avrdude: 470 bytes of flash verified