Forum: Mikrocontroller und Digitale Elektronik Attiny841 kein PWM Signal


von Robert D. (robert_d15)


Lesenswert?

Hallo zusammen,

ich möchte am PIN PA7 eine PWM mit timer0 generieren. Leider bekomme ich 
überhaupt kein Signal.

DDRA |= (1<<PORTA7); // PA7 auf Output

// PWM am PIN PA7 aktivieren
TOCPMSA1 = (1<<TOCC6S0);
TOCPMCOE = (1<<TOCC6OE);

// Compare Output Mode, Phase Correct PWM Mode (siehe Tabelle 11-7 auf 
Seite 87)
TCCR0A = (1<<COM0B1);

// PWM, Phase Correct (siehe Tabelle 11-8 auf Seite 87) mit TOP OCRA
TCCR0A = (1<<WGM00) | (1<<WGM02);

// Vorteiler auf 256 => f = CPU_8MHZ/256
TCCR0B |=  (1<<CS02);
// PWM 50%
OCR0A = 127;

CPU läuft mit geändert Fusbits mit 8MHz. Bitte um Hilfe und Tipps. 
Herzlichen DANK

von S. Landolt (Gast)


Lesenswert?

> TCCR0A = (1<<COM0B1);
> TCCR0A = (1<<WGM00) | (1<<WGM02);

Durch die zweite Zeile wird der Wert aus der ersten überschrieben, also 
'|=' verwenden.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Unabhängig davon musst Du die betreffenden TOCC-Ausgänge "enablen" Das 
Register befindet sich bei der Beschreibung der 16-Bit-Timer, TOCPMCOE 
heißt es.

von Robert D. (robert_d15)


Lesenswert?

Vielen Dank für die Hinweise und Tipps. Ich habe den Code korregiert:

// PA7 as output
DDRA = (1 << PINA7);
// configure 8 bit timer0 as PWM
TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B0); // PWM Modus, 
non-inverting mode
TCCR0B = (1 << CS01); // Prescaler 8

//TOCPMSA0 = (0 << TOCC3S0);
TOCPMSA1 = (1<<TOCC6S0); // select TOCC6 (PA7) for output compare OC0B

TOCPMCOE |= (1 << TOCC6OE); // enable mux channel output
OCR0B = 8; // duty cycle (0...255)

Leider immer noch kein Signal am Pin. Woram kann es liegen? werdenhier 
DDRA Register (siehe PINA7 Bezeichung) und TOCPMSA1 mit TOCPMCOE richtig 
eingestellt?

Danke für die Tipps

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Setze mal anstelle COM0B0 das Bit COM0B1.

Und TOCPSMA1 muss komplett 0 sein.

von Robert D. (robert_d15)


Lesenswert?

Das setzen auf COM0B1 ist leider trotzdem kein Siganl am Pin. Hier 
nochmal der gesamte Code im Überblick:

int main(void)
{

        PUEA &= ~ (1<<PORTA7); // Pull up on PA7 disabled
  PORTA &= ~ (1<<PORTA7);
  // PA7 as output
  DDRA |= (1 << PORTA7);

  // configure 8 bit timer0 as PWM
  TCCR0A |= (1 << WGM01) | (1 << WGM00) | (1 << COM0B1); // PWM Modus, 
non-inverting mode
  TCCR0B |= (1 << CS01); // Prescaler 8

  // select TOCC6 (PA7) for output compare OC0B
  TOCPMSA0 = 0x00;
  TOCPMSA1 |= (1<<TOCC6S0) | (1 << TOCC6S1);

  TOCPMCOE |= (1 << TOCC6OE) ; // enable mux channel output
  OCR0A = 127; // duty cycle 50%

  sei();

  while(1)
  {

  }
}

Bitte um weitere Hinweise und Tipps

von Robert D. (robert_d15)


Lesenswert?

Knut B. schrieb:
> Setze mal anstelle COM0B0 das Bit COM0B1.
>
> Und TOCPSMA1 muss komplett 0 sein.

Beides leider ohne Erfolg.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ich schick nachher noch mal was in ASM, dann kannst Du es ableiten. 
Grundsätzlich stimmt Dein Code bis auf TOCPSMA1, aber das hattest Du ja 
noch geändert.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

So, wie gesagt. In meiner Anwendung sind alle Timer aktiv, deswegen die 
entsprechende Init. Timer0 geht mit OCR0B auf TOCC2 raus. Musst Du also 
passig ändern.

1
 
2
;setup Ports
3
 ldi  Temp, 0b11101011
4
 out  DDRA, Temp
5
 ldi  Temp, 0b00001000
6
 out  PortA, Temp
7
8
...
9
10
11
;setup Timer0 (Timebase)
12
 ldi  Temp, (1<<COM0B1)|(1<<WGM01)|(1<<WGM00)
13
 out  TCCR0A, Temp                                  ;Fast PWM, noninverting
14
 ldi  Temp, (0<<CS02)|(0<<CS01)|(1<<CS00)                        ;Prescaler 1
15
 out  TCCR0B, Temp
16
 ldi  Temp, 255                                    ;Charger off
17
 out  OCR0B, Temp
18
19
 ldi  Temp, 0b00000000                                ;OC0B routed to TOCC2 output
20
 sts  TOCPMSA0, Temp    
21
22
23
 ldi  Temp, 0b11110100                                ;TOCC7/TOCC6/TOCC4/TOCC4/TOCC2 output enabled
24
 sts  TOCPMCOE, Temp

von Werner (Gast)


Lesenswert?

Das:
> DDRA |= (1<<PORTA7); // PA7 auf Output

und das:
 ldi  Temp, 0b11101011
 out  DDRA, Temp

passt für micht nicht zusammen.

Wie ist denn PORTA7 bei Dir definiert?
Vielleicht mal mit

 DDRA |= (1<<DDA7); // PA7 auf Output
(müsste ja wahrscheinlich
 DDRA |= 0b00000001 sein)

ausprobieren.

Werner

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Werner schrieb:
> DDRA |= (1<<DDA7); // PA7 auf Output
> (müsste ja wahrscheinlich
>  DDRA |= 0b00000001 sein)

Nö, 0b10000000.

von Werner (Gast)


Lesenswert?

Knut B. schrieb:
> Nö, 0b10000000.

Klar. Hab zu schnell geschriebenm. Asche auf mein Haupt. facepalm

von Robert D. (robert_d15)


Angehängte Dateien:

Lesenswert?

Vielen Dank an euch für die Hinweise und Tipps. Jetzt funktioniert es!!!
Am Anfang hatte ich Probleme, da der OCR0B Register für die Pulsweite 
nicht definiert war. Hier nun ein Beispiel mit 122 HZ PWM und 50% duty 
cycle mit einem Bild als Beweis :-)

#include "headerfiles.h"

int main(void)
{
  PUEA &= ~ (1<<PORTA7);  // Pull up off
  PORTA &= ~ (1<<PORTA7); // reset Port A7
  DDRA |= (1 << DDRA7); // PA7 as output

  // configure 8 bit timer0
  TCCR0A |=  (1 << WGM00) | (1 << WGM01) | (1 << COM0B1); // fast PWM 
Modus, non-inverting mode
  TCCR0B |= (1 << WGM02); // set TOP counter OCR0A

  // select TOCC6 (PA7) for output compare OC0B
  TOCPMSA0 |= 0x00;
  TOCPMSA1 |= 0x00; // (1<<TOCC6S0) => warum 0x00?

  TOCPMCOE |= (1 << TOCC6OE); // enable mux channel output (PA7)

  OCR0A = 255; // PWM Frequenz f = CPU/prescaler/OCR0A = 
8000000/1024/255 =~ 122 Hz ~ 8ms
  OCR0B = 127; // Pulsweite (duty cycle) 50% ~ 4ms

  TCCR0B |=  (1 << CS02); // start timer0 with prescaler 1024

  sei(); // enable interrupts

  while(1)
  {
           TO DO...
  }
}

Eine Frage hätte ich: Warum muss TOCPMSA1 auf 0x00 gesetzt werden? 
Welchen Sinn macht dann dieser Register?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

In TOCPSMA1 steckt die Kodierung der Timer OCRs für TOCC4 bis TOCC7, in 
Deinem Fall also auch für TOCC6. Da Du OCR0B verwenden willst, lauten 
die Bits dafür 00. Da Du andere Timer noch nicht verwendest, ist es 
klug, auch diese Bits erst einmal auf 0 zu lassen, damit Du nicht 
zusätzlich verwirrt wirst. Wenn Du andere OCRs verwenden willst, kannst 
Du die betreffenden Bits selbstverständlich auch manipulieren. Aber 
einen Schritt nach dem anderen und durch Probieren das Datenblatt 
verstehen.

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.