Hallo,
ich hab ein Problem mit dem Atmega88 und der PWM. Ich hatte die PWM
bereits am Laufen, habe dann aber wohl irgendwie einen Fehler
eingebaut... leider kann ich diesen einfach nicht finden.
1
voidinitPWM()
2
{
3
// Fast PWM 10bit (WGM10,WGM11,WGM12,!WGM13), clear on compare match (COM1A1,!COM1A0)
// setting CS10 to one starts -> leave it 0 for init
7
TCCR1B=(1<<WGM12);
8
// Timer to 0
9
TCNT1L=0;
10
TCNT1H=0;
11
// compare register to 0
12
OCR1AL=0;
13
OCR1AH=0;
14
// PB1 is OC1A -> set output
15
DDRB|=(1<<PB1);
16
}
17
18
voidsetPWM(uint16_thightime)
19
{
20
//10bit pwm, make sure upper 6bits are 0
21
OCR1AL=(uint8_t)hightime;
22
OCR1AH=(uint8_t)((hightime>>8)&0x0003);
23
}
24
25
voidstartPWM()
26
{
27
TCCR1B|=(1<<CS10);
28
}
29
30
31
intmain()
32
{
33
initPWM();
34
setPWM(0x100);
35
startPWM();
36
while(1);
37
}
Mit dem Code möchte ich die PWM eigentlich initialisieren und starten.
Der OC1A Pin ist allerdings unabhängig von dem Wert den ich mit setPWM()
setze genau 1 Clock Cycle HIGH, dann den Rest der Periode LOW.
Viele Grüße
Stefan
Hallo,
ich hab jetzt noch eine Weile rumgespielt und den Code aus dem eigenen
Testprojekt genommen (Testprojekt hat nur oben genannten Code
beinhaltet).
Im Zusammenhang mit anderem Code funktioniert die PWM mit oben
vorgenommenen Einstellungen nun.
Was ist da passiert? Hat der Compiler die While-Schleife wegoptimiert...
wäre ja logisch... aber springt er dann komplett auf "aus"? Also ist es
normal, dass er dann auch keine PWM mehr ausührt?
Viele Grüße
Stefan
Hi
> OCR1AL = (uint8_t)hightime;> OCR1AH = (uint8_t)((hightime>>8)&0x0003);
Die Reihenfolge ist falsch. Erst das H- und dann das L-Register
schreiben.
MfG Spess
Hallo spess,
herzlichen Dank für Deine Antwort. Ich habe die Reihenfolge nun
geändert. Im Testprojekt hat sich dadurch leider nichts geändert.
Immernoch nur 1 clock cycle High.
Viele Grüße
Stefan
Hallo Andreas,
ja sowohl im setPWM, als auch im initPWM. Zur Vorsicht habe ich nun auch
noch TCNT1H/L gedreht. Hat leider auch nichts bewirkt.
Viele Grüße
Stefan
Hallo,
neu compiliert hatte ich :)
hier das Assembly... leider sieht es nicht sehr aufgeräumt auf. Ich habe
noch nie etwas mit Assembler gemacht und es einfach aus dem Disassembly
Fenster beim debuggen kopiert, ich hoffe das ist in Ordnung (wusste
sonst keine Möglichkeit).
Viele Grüße
Stefan
Hallo,
in dem File zuvor hatte ich noch etwas rumgespielt und vergessen das
auszukommentieren. Hier noch einmal der Assembler Code des Quellcodes
wie ich ihn oben gepostet hatte.
Viele Grüße
Stefan
Hi
Auf den ersten Blick:
1. Das ist nicht das obige Programm. Ach nicht das korrigierte.
2. Hast du beim compilieren keine Warnungen oder Fehlermeldungen
bekommen?
MfG Spess
+00000024: 93800080 STS 0x0080,R24 Store direct to data space
3
11: TCCR1B = (1<<WGM12);
4
+00000026: E088 LDI R24,0x08 Load immediate
5
+00000027: 93800081 STS 0x0081,R24 Store direct to data space
6
13: TCNT1H = 0;
7
+00000029: 92100085 STS 0x0085,R1 Store direct to data space
8
14: TCNT1L = 0;
9
+0000002B: 92100084 STS 0x0084,R1 Store direct to data space
10
17: OCR1AH = 0;
11
+0000002D: 92100089 STS 0x0089,R1 Store direct to data space
12
18: OCR1AL = 0;
13
+0000002F: 92100088 STS 0x0088,R1 Store direct to data space
14
21: DDRB |= (1<<PB1);
15
+00000031: 9A21 SBI 0x04,1 Set bit in I/O register
16
22: }
17
+00000032: 9508 RET Subroutine return
->
1
+00000046: E081 LDI R24,0x01 Load immediate
2
+00000047: 93800089 STS 0x0089,R24 Store direct to data space
3
28: OCR1AL = (uint8_t)hightime;
4
+00000049: 92100088 STS 0x0088,R1 Store direct to data space
5
33: TCCR1B |= (1<<CS10);
6
+0000004B: 91800081 LDS R24,0x0081 Load direct from data space
7
+0000004D: 6081 ORI R24,0x01 Logical OR with immediate
8
+0000004E: 93800081 STS 0x0081,R24 Store direct to data space
9
+00000050: CFFF RJMP PC-0x0000 Relative jump
Was mir hierbei auffällt ist, dass er niemals diese Zeile des C
Quellcodes ausführt:
1
TCCR1A=(1<<WGM10)|(1<<WGM11)|(1<<COM1A1);
dies sollte ja nach dem ersten RCALL geschehen. Dass die PWM dann nicht
funktioniert erscheint plausibel, da in dieser Zeile ja der OC1A Pin
freigeschalten wird.
Dass dies nicht passiert kann ich nur irgendwie nicht mit meinem C
Quellcode in Verbindung bringen.
Viele Grüße
Stefan
Hallo,
ich hab mich jetzt mal angemeldet und hoffe, dass ich meine Beiträge nun
auch editieren kann. Mir ist nämlich schon wieder ein Fehler
unterlaufen: die Zeile wird doch ausgeführt, der C Code steht nur nicht
im Kommentar des Dissassembly.
Was bei der Simulation passiert:
Alle Register werden gesetzt, dann bleibt der Code für immer im letzten
Relative Jump. Nun beginnt der Timer zu zählen.
Timer:
1) läuft nun von 0x00 bis 0x100 und setzt Output Compare Flag 1A (hätte
erwartet, dass das Flag von Beginn an gesetzt ist, bis 0x100 erreicht
wird und dann auf 0 gesetzt wird. Nicht umgekehrt, da COM1A1=1 COM1A0=0)
2) läuft weiter bis 0x3FF (wie erwartet)
3) zählt von 0x3FF runter auf 0 (hätte hier erwartet, dass er auf 0
springt, da Fast PWM: WGM10=WGM11=WGM12=1 WGM13=0)
4) bei 0 setzt er TimerOverflowFlag und Output Compare Flag 1B und zählt
zurück auf 0x3FF.
5) ab jetzt wird auf 0x3FF gezählt und zurück auf 0 usw. (Flags werden
nicht mehr geändert)
Die Register sind wie oben genannt gesetzt (Fast PWM, Clear OCA1 on
Compare Match, Set at BOTTOM).
Viele Grüße
Stefan