PWM Problem: Pin nur 1 Clk Cycle High

Gast #1636133
Lesenswert?

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
void initPWM()
2
{
3
  // Fast PWM 10bit (WGM10,WGM11,WGM12,!WGM13), clear on compare match (COM1A1,!COM1A0)
4
  TCCR1A = (1<<WGM10) | (1<<WGM11) | (1<<COM1A1);
5
  // prescale of 1 @ 10bit -> PWM = 7.8kHz (CS10,!CS11,!CS12)
6
  // 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
void setPWM(uint16_t hightime)
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
void startPWM()
26
{
27
  TCCR1B |= (1<<CS10);
28
}
29

30

31
int main()
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
Gast #1636274
Lesenswert?

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
Gast #1636502
Lesenswert?

Hallo,

erstmal Entschuldigung wegen des falschen Assembler Code.
Ich habe jetzt noch einmal (diesmal direkt im Assembler) debuggt:

er steigt ein bei:
1
+00000045:   DFDD        RCALL     PC-0x0022      Relative call subroutine
->
1
+00000023:   E883        LDI       R24,0x83       Load immediate
2
+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
#1636530
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren