ATTiny85, Timer 1 PWM an PB1

Gast #6139943
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
Gast #6139982
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.
Gast #6139995
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.
Gast #6140004
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.
Gast #6140044
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.
Gast #6140556
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.
Gast #6140863
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!

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