Forum: Mikrocontroller und Digitale Elektronik Problem bei PWM mit Atmega88 und Assembler


von A. B. (developer_x)


Lesenswert?

Sehr geehrtes Forum,
mal wieder habe ich ein Problem, und zwar möchte ich gerne
die PWM Kanäle OC1A und OC1B nutzen.

Dazu habe ich mir das Tutorial
https://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM#Fast_PWM
durchgelesen, ebenso wie den Abschnitt im Datasheet.

Ich habe eine LED an PB0 angeschlossen, um zu sehen wie stark die LED 
normal leuchtet, sowie eine zweite LED mit einem Kabel, das mit PB1 
verbunden ist, damit ich einen Helligkeitsunterschied feststellen kann. 
Dieses Kabel ist ein Flexwire auf einem Breadboard, welches ich dann zum 
Vergleich auch an PB2 stecken kann.

PB1 ist ja der PWM Kanal OC1A, und PB2 ist ja der PWM Kanal OC1B.
Das mit OC1A funktioniert, die LED leuchtet, aber eben gedimmt.
Das mit OC1B funktioniert nicht, die LED ist aus.

Sogar wenn ich den Code zum Setzen von OCR1AH/L auskommentierte, 
leuchtet die LED am Ausgang von PB01 weiter, und zwar in dieser 
Dimmstufe, und am Ausgang PB02 passiert weiterhin nichts.
Wie kann das sein?
1
.include "m88def.inc"   
2
3
/*
4
Eine LED soll gedimmt werden
5
*/
6
7
.CSEG 
8
.DEF temp1 = R17
9
10
// Stackpointer initialisieren
11
LDI R16, low(RAMEND)
12
OUT SPL, R16
13
LDI R16, high(RAMEND)
14
OUT SPH, R16
15
16
// Richtung der IO Ports definieren
17
LDI R16, 0b11111111    // 1=Output, 0=Input
18
OUT DDRB, R16
19
SBI PORTB, PB0
20
21
//PWM_INIT:
22
  // Einstellen des PWM, Timer mit CPU Takt eingestellt, WG-Modus 14
23
  LDI R16, (1<<COM1A1) | (1<<WGM11) 
24
  STS TCCR1A, R16
25
26
  LDI R16, (1<<WGM13) | (1<<WGM12) | (1<<CS00)
27
  STS TCCR1B, R16
28
29
  //  Einstellen des TOP Wertes
30
  LDI R16, 0
31
  STS ICR1H, R16
32
33
  LDI R16, 200
34
  STS ICR1L, R16
35
36
  // Einstellen des Compare Wertes und wählen des Kanals
37
  LDI R16, 0
38
  STS OCR1AH, R16
39
40
  LDI R16, 10
41
  STS OCR1AL, R16
42
43
  LDI R16, 0
44
  STS OCR1BH, R16
45
46
  LDI R16, 50
47
  STS OCR1BL, R16
48
49
//RET
50
51
// Main Schleife
52
53
MAIN:
54
RJMP MAIN

Was ich des Weiteren fragen wollte, weil das nicht im Datasheet steht 
und auch nicht im Tut: Kann man dann zum Nutzen der anderen beiden 16 
Bit PWM Kanäle OC2A und OC2B, an den Pins PB3 und PD3, einfach dieselben 
Register, einfach mit einer "2" notiert, sprich TCCR2A, TCCR2B, 
ICR2(H/L) und OCR2(A/B)(H/L), verwenden?

Danke für eine Antwort,
m.f.G.: Developer_X

von A. B. (developer_x)


Lesenswert?

Der Einfachheit halber habe ich jetzt 3 LEDs nebeneinander, jeweils mit 
PB0, PB1 und PB2 verbunden.

von spess53 (Gast)


Lesenswert?

Hi

Du solltest auch COM1B1/COM1B0 einstellen.

MfG spess

von A. B. (developer_x)


Lesenswert?

Ah!
Danke sehr! Jetzt klappt es.
War ja wieder klar dass ich das übersehe xd.

Hast du auch eine Antwort auf meine Frage:
A. B. schrieb:
> Was ich des Weiteren fragen wollte, weil das nicht im Datasheet steht
> und auch nicht im Tut: Kann man dann zum Nutzen der anderen beiden 16
> Bit PWM Kanäle OC2A und OC2B, an den Pins PB3 und PD3, einfach dieselben
> Register, einfach mit einer "2" notiert, sprich TCCR2A, TCCR2B,
> ICR2(H/L) und OCR2(A/B)(H/L), verwenden?
Denn einfach ne zwei schreiben funktioniert definitiv nicht.

Danke für eine Antwort,
m.f.G.: Developer_X

von spess53 (Gast)


Lesenswert?

Hi

Ich weiß nicht, ob ich dich richtig verstanden habe: Timer2 ist ein 
8-Bit Timer. Da gibt es nur die Register OCR2B, OCR2A, TCNT2, TCCR2B und 
TCCR2A.

MfG spess

von A. B. (developer_x)


Lesenswert?

Also im Datenblatt gibt es Kapitel 15, da geht es um den 8Bit Timer mit 
Erklärung wie man die PWM Kanäle OC0A und OC0B verwendet, wenn ich das 
richtig verstanden habe. Und hier kann man, im Gegensatz zu den OC1A und 
OC1B leider nur über interrupts eine PWM erzeugen, denn man kann hier 
nur den TOP Wert, allerdings keinen COMPARE Wert setzen.

Kapitel 16 behandelt ja die OC1A und OC1B.

Worum es mir geht ist, wie man die Kanäle OC2A und OC2B nutzen kann.
...
Ah, Kapitel 18, sehe ich gerade.

Ich habe das schonmal mit den Kanälen OC0A und OC0B versucht, aber 
leider ohne Erfolg:
1
.include "m88def.inc"   
2
3
/*
4
  Eine LED soll gedimmt werden
5
*/
6
7
.CSEG 
8
.DEF temp1 = R17
9
10
// Stackpointer initialisieren
11
LDI R16, low(RAMEND)
12
OUT SPL, R16
13
LDI R16, high(RAMEND)
14
OUT SPH, R16
15
16
// Richtung der IO Ports definieren
17
LDI R16, 0b11111111    // 1=Output, 0=Input
18
OUT DDRB, R16
19
OUT DDRD, R16
20
SBI PORTB, PB0
21
22
23
//PWM_INIT_CHANNELS_0
24
  // Einstellen des PWM, Timer mit CPU Takt eingestellt, WG-Modus 3
25
  LDI R16, (1<<COM0A1) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00)
26
  STS TCCR0A, R16
27
28
  LDI R16, (1<<CS00)
29
  STS TCCR0B, R16
30
31
  // Einstellen des Compare Wertes und wählen des Kanals
32
  LDI R16, 10
33
  STS OCR0A, R16
34
35
  LDI R16, 50
36
  STS OCR0B, R16
37
38
39
// Main Schleife
40
41
MAIN:
42
RJMP MAIN

Ich hab die LEDs an PD5 und PD6 gesteckt, und keine von beiden leuchtet.

Ich gehe mit meinem Code davon aus, dass der Counter bei dem Compare 
Wert wechselt, und der Top Wert bei PWM Kanälen basierend auf den 8 Bit 
Timern immer 255 beträgt.

Was mache ich hier falsch?

: Bearbeitet durch User
von A. B. (developer_x)


Lesenswert?

Ah ich sehe gerade, dass das mit 8 Bit Timern nur über Interrupts geht, 
oder liege ich da falsch?

In allen Modes of Operation in Kapitel 15.7 scheint es immer nur darum 
zu gehen, dass man entweder Flags überwacht oder Interrupts.
Oder?

Keiner dieser Modi funktioniert wie die viel einfacher handhabbaren auf 
Basis der 16 Bit Timer.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

Die vorhandenen PWM-Modi funktionieren bei den 8-Bit-Timern genau so wie 
bei den 16-Bit-Timern. Wesentlicher Unterschied ist, das da kein 
IC-Register existiert mit dem man den Top-Wert einstellen kann. Entweder 
man benutzt den festen Wert $FF als Top-Wert oder man opfert Compare 
Register A für einen eibstellbaren Top-Wert.

MfG Spess

von A. B. (developer_x)


Lesenswert?

Ja ok, aber wie siehts aus mit dem invertieren des Signals, muss man das 
selbst machen, oder macht er das dann, weil mein Code liefert solch ein 
Ergebnis momentan leider nicht :( ob wohl ich FastPWM ausgewählt habe.

von spess53 (Gast)


Lesenswert?

Hi

>Ja ok, aber wie siehts aus mit dem invertieren des Signals, ...

Wozu sind denn die COM-Bits?

MfG Spess

von A. B. (developer_x)


Lesenswert?

Ich habe jetzt folgende Einestellung:
COM0A0 und COM0B0 gesetzt.
Ich will ja, dass es toggelt, jetzt steht in der Tabelle,
dass er toggelt, wenn WGM02 aktiviert ist, wir reden ja von der Tabelle 
des FASTPWM, und dann haben wir das problem, dass wir den Modus 7 
auswählen, bei welchem TOP OCR0A gleicht, und es nie zum Toggeln kommt.

Mit welcher Einstellungen ist es denn möglich mein Vorhaben zu 
realisieren?

von A. B. (developer_x)


Lesenswert?

Ich sehe keine Möglichkeit

von spess53 (Gast)


Lesenswert?

Hi

>Ich will ja, dass es toggelt, ...

Sicher? Das würde aus OC0A eine CTC, aber keine PWM machen. Zwei Fast 
PWM Ausgänge bekommst du nur im Mode3

MfG Spess

von A. B. (developer_x)


Lesenswert?

Also:
Ich stelle Modus 3 ein, schau dann in die Tabelle zur Setzung von 
COM0AX-Bits, die für den Modus FASTPWM, und dort steht, S101, letzte 
Tabelle, dritte Zeile, 1,0, Clear OC0A on compare match, set OC0A at 
BOTTOM,
(non-inverting mode).

Das habe ich alles eingestellt, und trotzdem ist nichts an der LED zu 
sehen.
1
.include "m88def.inc"   
2
3
/*
4
  Eine LED soll gedimmt werden
5
*/
6
7
.CSEG 
8
.DEF temp1 = R17
9
10
// Stackpointer initialisieren
11
LDI R16, low(RAMEND)
12
OUT SPL, R16
13
LDI R16, high(RAMEND)
14
OUT SPH, R16
15
16
// Richtung der IO Ports definieren
17
LDI R16, 0b11111111    // 1=Output, 0=Input
18
OUT DDRB, R16
19
OUT DDRD, R16
20
SBI PORTB, PB0
21
22
//PWM_INIT_CHANNELS_0
23
  // Einstellen des PWM, Timer mit CPU Takt eingestellt, WG-Modus 3
24
  LDI R16, (1<<COM0A1) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00)
25
  STS TCCR0A, R16
26
27
  LDI R16, (1<<CS00)
28
  STS TCCR0B, R16
29
30
  // Einstellen des Compare Wertes und wählen des Kanals
31
  LDI R16, 10
32
  STS OCR0A, R16
33
34
  LDI R16, 50
35
  STS OCR0B, R16
36
37
// Main Schleife
38
39
MAIN:
40
RJMP MAIN

von A. B. (developer_x)


Lesenswert?

Ich bin ganz ehrlich, ich habe das Datasheet jetzt drei viermal gelesen 
und alle möglichen Kombintationen probiert, was ist denn nun die 
richtige Konfiguration, so komme ich nie drauf, das kostet einfach Zeit 
und Nerven, ohne dass dabei etwas rauskommt :(.

von spess53 (Gast)


Lesenswert?

Hi

> was ist denn nun die
>richtige Konfiguration, so komme ich nie drauf, das kostet einfach Zeit
>und Nerven, ohne dass dabei etwas rauskommt :(.

Benutze einfach für die Ausgaben auf die Timerregister out statt sts. 
Die liegen nämlich im normalen IO-Bereich.

MfG Spess

von A. B. (developer_x)


Lesenswert?

Oh man. Schon wieder dieser Fehler, den hab ich erst gemacht^^.

Danke jetzt funktioniert es endlich mal.

Also in Zukunft auch das im Debugger prüfen, ob wirklich alles gesetzt 
wird. Ist notiert.

Danke für deine Hilfe!
m.f.G.: Developer_X

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.