Forum: Mikrocontroller und Digitale Elektronik PWM Problem: Pin nur 1 Clk Cycle High


von Stefan (Gast)


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

von Stefan (Gast)


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

von spess53 (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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

von Andreas F. (aferber)


Lesenswert?

Stefan schrieb:
> Ich habe die Reihenfolge nun
> geändert.

Auch in initPWM()?

Andreas

von Stefan (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>Hat leider auch nichts bewirkt.

Kannst du mal den Assemblercode des Programms anhängen.

MfG Spess

P.S. Neu compiliert hast du aber?

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

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

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>in dem File zuvor hatte ich noch etwas rumgespielt und vergessen das

Hatte ich gemerkt.

MfG Spess

von Stefan (Gast)


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

von Stefan K. (stefankoehler)


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

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.