Forum: Mikrocontroller und Digitale Elektronik ATTiny85, Timer 1 PWM an PB1


von T. (Gast)


Lesenswert?

Hallo in die Runde,

ich bin schon längere Zeit stiller Mitleser, jetzt habe ich auch mal 
eine konkrete Frage/ ein konkretes Problem:

Bei Versuchen mit einem ATTiny85 versuche ich zu Zeit, PWM zum laufen zu 
bringen.
Ich habe Timer 1 auf ~3,9 kHz gesetzt:
cli();
  TCCR1 = TCCR1 & 0b11110000 | ((0 << CS13) | (1 << CS12) | (0 << CS11) 
| (0 << CS10));
  sei();

Nun setzte ich folgend PB4 auf 127 (ca. 50/50 an/aus)
// connect pwm to pin on timer 1, channel B
pinMode(4, OUTPUT);
sbi(GTCCR, COM1B1);
OCR1B = 127; // set pwm duty

Das funktioniert. Ebenso, wenn ich Timer 0 (mit seinen weiterhin 490 Hz) 
an PB1 hänge:
pinMode(1, OUTPUT);
sbi(TCCR0A, COM0B1);
OCR0B = 127; // set pwm duty

Das funktioniert auch. Jedoch hätte ich am PB1 lieber den Timer 1 
genutzt, diese alternative Belegung ist ja im Datenblatt erläutert.

Entsprechend habe ich folgenden Code:
pinMode(1, OUTPUT);
sbi(TCCR1, COM1A1);
OCR1A = 127; // set pwm duty

Das funktioniert aber nicht. Habt ihr eine Idee warum? Möglicherweise 
habe ich noch etwas vergessen.

Danke im Voraus

von S. Landolt (Gast)


Lesenswert?

Wie sieht das vollständige Programm aus?

von T. (Gast)


Lesenswert?

Ich schreibe das in der Arduino IDE:
1
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
2
3
void setup() {
4
  // Timer 1 auf 3906 Hz (PWM-Ausgänge 1 und 4)
5
  cli();
6
  TCCR1 = TCCR1 & 0b11110000 | ((0 << CS13) | (1 << CS12) | (0 << CS11) | (0 << CS10));
7
  sei();
8
9
  pinMode(1, OUTPUT);
10
  sbi(TCCR0A, COM0B1);
11
  //cbi(TCCR0A, COM0B0);
12
  OCR0B = 127; // set pwm duty
13
14
  while(1);
15
}

Den mittleren Block ersetze ich entsprechend. Ich habe zur Fehlersuche 
im Prinzip alles außer dieser Funktion entfernt.

von S. Landolt (Gast)


Lesenswert?

>   OCR0B = 127; // set pwm duty

Ich denke, das sollte OCR0A sein.

von S. Landolt (Gast)


Lesenswert?

Entschuldigung, das war Unsinn von mir.

Ich denke, wir reden hier vom Timer1?

von T. (Gast)


Lesenswert?

Ja:
1
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
2
3
void setup() {
4
  // Timer 1 auf 3906 Hz (PWM-Ausgänge 1 und 4)
5
  cli();
6
  TCCR1 = TCCR1 & 0b11110000 | ((0 << CS13) | (1 << CS12) | (0 << CS11) | (0 << CS10));
7
  sei();
8
9
  pinMode(1, OUTPUT);
10
  sbi(TCCR1, COM1A1);
11
  OCR1A = 127; // set pwm duty
12
13
  while(1);
14
}


Das funktioniert nicht, PB1 bleibt aus.

von S. Landolt (Gast)


Lesenswert?

Das wundert mich: dies, in Assembler, läuft hier:
1
 sbi    DDRB,1
2
 puti   TCCR1,(1<<CTC1)|(1<<PWM1A)|(1<<COM1A0) |(1<<CS11)
3
 puti   OCR1A,127

Ich sehe jetzt keinen wesentlichen Unterschied zu Ihrem.

von S. Landolt (Gast)


Lesenswert?

Ah, doch, TCCR1 steht nach Reset auf 0, folglich ist
1
TCCR1 = TCCR1 & irgendetwas
immer 0.

von S. Landolt (Gast)


Lesenswert?

in C:
1
#include <avr/io.h>
2
int main(void)
3
{
4
  TCCR1 = (1<<CTC1)|(1<<PWM1A)|(1<<COM1A0) |(1<<CS12);
5
  DDRB = (1<<PB1);
6
  OCR1A = 127;
7
    while (1) 
8
    {
9
    }
10
}

von T. (Gast)


Lesenswert?

Was bedeutet das jetzt für mich?
So ganz habe ich den letzten Kommentar auch nicht verstanden :)

von T. (Gast)


Lesenswert?

S. Landolt schrieb:
> in C:#include <avr/io.h>
> int main(void)
> {
>   TCCR1 = (1<<CTC1)|(1<<PWM1A)|(1<<COM1A0) |(1<<CS12);
>   DDRB = (1<<PB1);
>   OCR1A = 127;
>     while (1)
>     {
>     }
> }

Mein letzter Beitrag bezog sich auf den vorletzten von Ihnen. Danke, ich 
werde das testen und morgen Feedback geben.

von S. Landolt (Gast)


Lesenswert?

Noch ergänzend: bei CTC müsste eigentlich OCR1C zugewiesen werden (um 
die Frequenz der PWM einzustellen; folglich größer als OCR1A); dass es 
hier trotzdem funktioniert, liegt daran, dass bei Reset OCR1C=255 (0xFF) 
gesetzt ist.

von T. (Gast)


Lesenswert?

Einen schönen guten Morgen,

danke S. Landolt, es funktioniert jetzt. Parallel habe ich den Timer 1B 
auch so angepasst, der lief zwar vorher schon, aber jetzt ist es 
einheitlich.

Programm jetzt (Arduino IDE):
1
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
2
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
3
4
void setup() {
5
  cli();
6
  TCCR1 = ((1<<CTC1) | (1<<PWM1A) | (1<<CS12)); //(1<<COM1A1) | 
7
  GTCCR = ((1<<PWM1B)); // | (1<<COM1B1));
8
  sei();
9
}
10
11
void loop() {
12
  /*
13
  * Abschnitt um Duty-Cycle zu ermitteln
14
  */
15
  analogWriteC(pb1, value_a);
16
  analogWriteC(pb4, value_b);
17
}
18
19
void analogWriteC(uint8_t pin, int val) {
20
  pinMode(pin, OUTPUT);
21
  if (pin == 1) {       // für Pin 1
22
    if (val <= 0) {     // aus 
23
      digitalWrite(pin, LOW);
24
      cbi(TCCR1, COM1A1);     // Timer trennnen
25
    } else if (val >= 255) {  // an
26
      digitalWrite(pin, HIGH);
27
      cbi(TCCR1, COM1A1);     // Timer trennnen
28
    } else { // pwm
29
      sbi(TCCR1, COM1A1);     // Timer verbinden
30
      OCR1A = val;            // Duty-Cycle setzten
31
    }
32
  } else if (pin==4) { // ebenso für Pin 4
33
    if (val <= 0) {
34
      digitalWrite(pin, LOW);
35
      cbi(GTCCR, COM1B1);
36
    } else if (val >= 255) {
37
      digitalWrite(pin, HIGH);
38
      cbi(GTCCR, COM1B1);
39
    } else {
40
      sbi(GTCCR, COM1B1);
41
      OCR1B = val;
42
    }
43
  }
44
}

Danke!

von Karl M. (Gast)


Lesenswert?

Sorry,

einen Timer 1B gibt es nicht!

Wie kommt man darauf?

von S. Landolt (Gast)


Lesenswert?

> einen Timer 1B gibt es nicht!

Es gibt den Timer1-PulseWidthModulatorB.

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.