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