PWM auf PB3 Atmega 328 P

Gast #6536516
Lesenswert?

Hier der Code nochmal in Text Form

1
 //Achte immer darauf welche Pwm Pins welche Timer benötigen!
2

3
void setup(){ 
4
  // WGM22/WGM21/WGM20 all set -> Mode 7, fast PWM
5
  // Set OC2B at bottom, clear OC2B at compare match
6
  TCCR2A = 0;
7
  TCCR2B = 0;
8
  //Fast PWM Mode
9
  TCCR2B |= (1<<WGM22);
10
  TCCR2A |=(1<<WGM21);
11
  TCCR2A |=(1<<WGM20); 
12
  TCCR2A |= (1<<COM2A1);
13
    
14
  // prescaler = 8
15
  TCCR2B &= ~(1<<CS22);
16
  TCCR2B |= (1<<CS21);
17
  TCCR2B &= ~(1<<CS20);
18
  
19
  
20
  
21
  //Hier Frequenz einstellen wir lassen aber auf 10 kHz  
22
  OCR2A = 100;
23
  //Hier von 0-200 Dutycycle einstellen
24
  OCR2B = 0;
25
  //So schalten wir die Pwm ein bzw. aus
26
 
27
  DDRB |= (1<<PB3);
28

29
 
30
} 
31
void loop() {
32
 
33
 //Loop wird hier stark verlangsamt
34
 OCR2B = map(analogRead(A0),0,1023,0,200);
35
  
36
  }
Gast #6536607
Lesenswert?

OC2A (der Pin) wird abhängig von OCR2A (dem Register) gesetzt/gelöscht. 
Nicht abhängig von OCR2B.

Ich hab das im Datenblatt nicht geprüft, vermute aber anhand der 
Kommentare "Frequenz einstellen", du hast einen CTC-Modus ausgewählt, 
d.h. der Timer läuft hoch bis OCR2A. Dann kannst du OC2A nicht als 
PWM-Ausgang verwenden, weil der Timer nie größer wird als OCR2A.

Das ist mit etwas anderen Worten das gleiche, was S. Landolt auch schon 
gesagt hat.

Es ergibt ferner im CTC-Modus keinen Sinn, wenn OCR2A 100 ist, in OCR2B 
Werte bis 200 zuzulassen. Der Timer läuft eh nur bis 100.

MfG, Arno
Gast #6536627
Lesenswert?

S. Landolt schrieb:
> Also entweder PWM im Modus 7 auf OC2B, das liegt auf PD3, oder PWM im
> Modus 3 auf OC2A (PB3), dann allerdings lässt sich die Frequenz nur sehr
> grob per Vorteiler einstellen.

Okay Danke also vielleicht erkläre ich mal mein Vorhaben. Ich möchte auf 
PB1,PB2 und PB3 eine PWM ausgeben im Mode 3 kann ich keinen Dutycycle 
einstellen. Ich benötige allerdings eine Frequenz von 10 kHz und einen 
variablen Dutycycle.
Beitrag #6536646 wurde von einem Moderator gelöscht.
Gast #6536695
Lesenswert?

Jup hab ich auch gemerkt den dutycycle kann man sehr wohl einstellen, 
hier noch mein fertiger code:
1
//Dutycycle
2
uint8_t dtc = 0;
3

4
void setup(){ 
5
 
6
  setPwmPin9_10();
7
  setPwmPin11();
8
 
9
  }
10
  
11
  void loop() {
12
 
13
  //Loop wird hier stark verlangsamt
14
  dtc = map(analogRead(A0),0,1023,0,255);
15
  OCR1A = dtc;
16
  OCR1B = dtc;
17
  OCR2A = dtc;
18
  
19
   
20
  }
21

22

23

24
  void setPwmPin9_10(){
25
  // Reset Timer Register
26
  TCCR1A = 0;
27
  TCCR1B = 0;
28
  //Fast PWM Mode 
29
  TCCR1A |= (1<<WGM10);
30
  TCCR1B |= (1<<WGM12);
31
  //Setze Compare Modi non inverting Mode!
32
  TCCR1A |= (1<<COM1B1);
33
  TCCR1A |= (1<<COM1A1);
34

35
  //Setze Prescaler 8
36
  TCCR1B &= ~(1<<CS10);
37
  TCCR1B |=  (1<<CS11);
38
  TCCR1B &= ~(1<<CS12);
39
  //Setze Compare Values
40
  OCR1B = 0;
41
  OCR1A = 0;
42
  //Setze Pin 9 und 10 für aktiven PWM ausgang
43
  DDRB |= (1<<PB1);
44
  DDRB |= (1<<PB2); 
45
 }
46

47
  void setPwmPin11(){
48
  // Reset Timer Register
49
  TCCR2A = 0;
50
  TCCR2B = 0;
51
  //Fast PWM Mode TOP 0xFF
52
  TCCR2A |=(1<<WGM21);
53
  TCCR2A |=(1<<WGM20); 
54
  //Setze Compare Modi non inverting Mode!
55
  TCCR2A |= (1<<COM2A1);
56
  // prescaler = 8
57
  TCCR2B &= ~(1<<CS22);
58
  TCCR2B |= (1<<CS21);
59
  TCCR2B &= ~(1<<CS20);
60
  //Setze Compare Value
61
  OCR2A = 0;
62
  //Setze Pin11 afür aktiven PWM ausgang
63
  DDRB |= (1<<PB3);
64
    
65
    
66
  }
Gast #6536697
Lesenswert?

> Habs hin bekommen danke :)

Prima!
Ich hatte nämlich übersehen, dass beim Timer2 ja auch noch durch 2^8 = 
256 geteilt wird, damit sieht es dann deutlich besser aus, z.B. 16 MHz 
/256 /8 = 7.8 kHz.
#6537555
Lesenswert?

Hallo,

auch wenn der Timer scheinbar das macht was er soll, sollte man in der 
Arduino IDE alle Timerregister (TCCRnx und TIMSKn) vorher löschen. Die 
werden mittels setup() im Hintergrund für analogWrite voreingestellt. 
Das schützt vor unliebsamen Überraschungen wenn der Timer plötzlich 
nicht das macht was er eigentlich sollte. Ich selbst beginne mit TCCRnB, 
damit der Timer erstmal gestoppt ist.

Für die Prescalereinstellerei noch 2 Funktionen die einem das Leben 
leichter machen. Kannste auf jeden Timer anpassen.
1
void runTimer1 (const unsigned int prescaler)
2
{
3
  switch (prescaler) {  
4
    case    1 : TCCR1B |= _BV(CS10);              break;
5
    case    8 : TCCR1B |= _BV(CS11);              break;
6
    case   64 : TCCR1B |= _BV(CS11) | _BV(CS10);  break;
7
    case  256 : TCCR1B |= _BV(CS12);              break;
8
    case 1024 : TCCR1B |= _BV(CS12) | _BV(CS10);  break;
9
    default :   break;
10
  }  
11
}
12

13

14
void stopTimer1 (void)
15
{
16
  TCCR1B &= ~( _BV(CS12) | _BV(CS11) | _BV(CS10) );
17
}

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