Problem bei PWM mit Atmega88 und Assembler

OP #4296556
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
OP #4296569
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
OP #4296593
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?
OP #4296595
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.
Gast #4296620
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
OP #4296644
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?
OP #4296726
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
Gast #4296750
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

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