Forum: Mikrocontroller und Digitale Elektronik Attiny861 10Bit PWM Timer1


von Martin (Gast)


Lesenswert?

Hallo Allerseits,

Habe ein kleines Problem mit dem Attiny861. Wahrscheinlich liegt es mehr 
an meinem Verständnis oder sehe den Wald vor lauter Bäumen nicht mehr.
Ich versuche eine PWM mit dem Timer1 zu erzeugen, was soweit erstmal 
funktioniert. Habe zur Zeit die PWM so eingestellt das ich eine Frequenz 
von 125kHz habe und den Tastgrad in 255 (8Bit) Schritten einstellen 
kann. Jetzt möchte ich aber die Schrittzahl erhöhen und laut Datenblatt 
ist dies auch möglich die OCR1x Register auf zehn Bit zu erweitern. 
Wobei dann einfach die zwei MSB in TC1H geschrieben werden sollen. 
Soweit so gut, nur habe ich dann das problem das ich den Tastgrad nicht 
nicht mehr auf nullbekomme.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
//LED-Steuerung
6
7
#define LED_Control 0
8
#define EN_EINGANG 3
9
#define LED_PWM 4
10
#define LED_ADW 5
11
#define LED_EIN(x) PORTA |= (1<<x)
12
#define LED_AUS(x) PORTA &= ~(1<<x)
13
14
15
//Topwert für Counter f(PWM) =125kHz
16
17
#define MAX_COUNT  0xFF //0xFF = 255
18
19
//Variablen
20
21
volatile uint8_t check1;
22
volatile uint8_t check2;
23
24
volatile int16_t HAND_PWM;
25
26
ISR(INT1_vect)
27
{
28
  check1 =check1 + 1;
29
    if (check1 == 1)
30
    {
31
    cli();
32
33
    LED_AUS(LED_Control);
34
    LED_AUS(LED_ADW);
35
    LED_AUS(LED_PWM);
36
37
      
38
      HAND_PWM = HAND_PWM + 1;
39
      OCR1B = HAND_PWM;
40
      
41
42
    sei();
43
    }
44
45
    if (check1 == 2)
46
    {
47
    cli();
48
      
49
    LED_EIN(LED_Control);
50
    LED_EIN(LED_ADW);
51
    LED_AUS(LED_PWM);
52
53
      
54
      HAND_PWM = HAND_PWM + 1;
55
      OCR1B = HAND_PWM;
56
      
57
    check1=0;
58
59
    sei();
60
    }
61
62
}
63
64
ISR(INT0_vect)
65
{
66
  check2 =check2 + 1;
67
    if (check2 == 1)
68
    {
69
    cli();
70
71
    LED_AUS(LED_Control);
72
    LED_AUS(LED_PWM);
73
    LED_AUS(LED_ADW);
74
75
      
76
      HAND_PWM = HAND_PWM - 1;
77
      OCR1B = HAND_PWM;
78
      
79
    sei();
80
    }
81
82
    if (check2 == 2)
83
    {
84
    cli();
85
86
    LED_EIN(LED_Control);
87
    LED_EIN(LED_PWM);
88
    LED_AUS(LED_ADW);
89
90
      
91
      HAND_PWM = HAND_PWM - 1;
92
      OCR1B = HAND_PWM;
93
    
94
     check2=0;
95
96
    sei();
97
    }
98
99
}
100
101
102
103
int main(void)
104
{
105
106
  HAND_PWM = 10;
107
  check1 =0;
108
  check2 =0;
109
  
110
  //Tastereingang PB6 (INT0) PWMausgang PB3
111
112
  DDRB =  (0<<PB6) | (0<<PB5) | (0<<PB4) | (1<<PB3); 
113
114
  //LEDausgänge PA0,4,5 Tastereingang PA2 (INT1)     
115
116
  DDRA = (1<<PA5) | (1<<PA4) | (1<<PA3) | (0<<PA2) | (1<<PA0); 
117
118
  //Pull_UPs für Taster
119
120
  PORTA |= (1<<PA2); 
121
122
  PORTB |= (1<<PB6);
123
  
124
  //Globale Interruptmaske
125
126
   GIMSK = (1<<INT1) | (1<<INT0);
127
  
128
  //steigende Flanke
129
130
  MCUCR = (1<<ISC01) | (1<<ISC00);
131
132
133
  //Timer 1 init
134
135
  TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) |
136
         (0<<FOC1A) | (0<<FOC1B) | (0<<PWM1A) | (1<<PWM1B);
137
  
138
  TCCR1B = (0<<PWM1X) | (0<<PSR1) | (0<<DTPS11) | (0<<DTPS10) |  (0b0000<<CS10); 
139
      
140
141
  TCCR1D = (0<<FPIE1) | (0<<FPEN1) | (0<<FPNC1) | (0<<FPES1) | 
142
       (0<<FPAC1) | (0<<FPF1) | (0<<WGM11) | (0<<WGM10);
143
144
145
146
  //PLL init und starten
147
148
  PLLCSR = (0<<LSM) | (1<<PCKE) | (1<<PLLE);
149
  _delay_us(40);
150
  _delay_us(40);
151
  _delay_us(40);
152
153
  //Top setzen
154
155
  TC1H = 0x01;
156
  OCR1C = 0xFF;
157
    
158
  //Zaehler setzen
159
160
  
161
  OCR1B = HAND_PWM;
162
163
164
  //Stabilisierung der PLL abwarten
165
  
166
    while(!(PLLCSR&0x01))
167
  {}
168
  
169
  //Enable Eingang des Treiber setzen
170
171
  LED_EIN(EN_EINGANG);
172
173
  //PWM starten
174
175
  TCCR1B |= (0b0001<<CS10);
176
177
  sei();
178
179
  while(1)
180
  {}    
181
}

Also vom Prinzip her lasse ich den Zähler bis OCR1C zählen, zur zeit 
also bis max. 255. Jedesmal wenn der zähler dann den Wert von OCR1B 
erreicht wird der Pegel an PIN B3 umgeschaltet. Jetzt besteht wie oben 
beschrieben das Problem wenn ich OCR1C mittels TC1H auf 10bit erweitere 
kann ich den Wert von OCR1B bis auf maximal 255 senken, da das Register 
TC1H für alle OCR1x gültig ist. Wie kann ich es nun schaffen das ich 
OCR1B trotzdem auf 0 bekomme??

Vielen Dank schonmal im Vorraus
Grüße

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Hallo!

Ich bastel auch seit einer Weile mit einem Attiny 261, die PWM da zu 
verstehen ist nicht wirklich einfach, zumal man das irgendwie nicht 
simulieren kann, der Simulator macht da nur Mist, der sich nicht mit der 
Wirklichkeit gleicht.

Zu deinem Problem würde ich einfach sagen, das du vor dem schreiben auf 
das OCR1B Byte eben das TNC1H = 0 setzen musst, um es zu ändern. Wenn du 
das Byte auslesen willst, liest du zuerst OCR1B und dann TNC1H. Ich 
denke, damit sollte das laut dem Codeexample im DAtenblatt erklärbar 
sein. Weil so wie ich das kapiere, ist das TNC1H Byte nur zum kopieren 
da, also nicht das, was in dem Byte steht, zählt für dein OCR1C. Also 
wenn du OCR1C beschreibst, musst du vorher in TNC1H den High-Wert 
schreiben. Und mit dem schreiben von OCR1C wird aus TNC1H der WErt mit 
in ein Register kopiert, auf das du direkt keinen Zugriff hast. So 
verstehe ich den Abschnitt 12.11. im Datenblatt.

Nur für mich so zur Info, was willst du eig bauen?


MfG Dennis

von Dennis H. (t1w2i3s4t5e6r)


Lesenswert?

Aso, noch ein Tip, schließe niemals Taster an den externen Interrupt an, 
es wird dir nicht viel Spaß bereiten, schau hier einfach mal im Forum 
bei Entprellung.


MfG Dennis

von Martin (Gast)


Lesenswert?

Huhu Dennis,

Ich habs mittlerweile auch rausgefunden das man das TC1H register 
einfach immer vor OCR1x setzen muss wie man es braucht.... war halt den 
Wald vor lauter Bäumen nicht mehr gesehen :) Zum Thema Taster ist kein 
Problem, da ich diese Hardwareseitig entprellt habe und die auch super 
funktonieren. Hätten auch auf anhieb funktioniert, wenn das Steckbrett 
was ich zu Testzwecken benutze nicht eine durchkontaktierung ( kaputt 
halt) auf den Reset gehabt haette. :) War bisschen ätzen weil bei jedem 
tastendruck sich dann der uC resettet hat. Aber wenn mans mal gefunden 
hat läufts super...

Ja was ich damit machen will. Der kleine Tiny wird die Steuerung für 
eine Kaskodenschaltung eines Hoch- und eines Tiefsetzstellers ( oder 
bevor ich geschlagen werde Step-Up bzw. Step-Down Wandler ;)). Also im 
Endeffekt möchte ich damit einen Schalter steuern, wobei der oben 
gepostete Code nur die halbe Wahrheit ist weil zusätzlich kommt noch der 
ADC zum Einsatz der für ne kleine Regelschleife missbraucht wird. Quasi 
das Konzept besteht darin eine PWM zu erzeugen die entsprechend der 
gemessenen Eingangs- und Ausgangsspannung den Tastgrad anpasst oder 
durch die Taster manuell mishandelt werden kann. Das Ganze im Rahmen 
einer Bachelorarbeit und die Schaltung soll später für Laborversuche für 
Studenten eingesetzt werden.

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.