Ich wollte eine PWM-Zeitschaltuhr bauen - PWM wird durch Potti geregelt und mit ADC gelesen und umgesetzt. Funzt gut. Jetzt soll der 2. Timer dazu dienen Das Signal An/Aus zu schalten nach einer Festen Zeit. Momentan wollte ich nur mal den Interrupt Testen und die Schaltung EIN schalten. Aber nichts passiert. Der Interrupt scheint nicht ausgeführt zu werden. Hier mein Code:
1 | #include "headers.h" |
2 | |
3 | // Globaler Status AN/Aus
|
4 | int status; |
5 | |
6 | |
7 | |
8 | ISR(SIG_OUTPUT_COMPARE1A) |
9 | {
|
10 | |
11 | status = 1; |
12 | }
|
13 | |
14 | |
15 | |
16 | |
17 | int main (void) |
18 | |
19 | {
|
20 | |
21 | uint16_t MyADC; |
22 | uint8_t tast; |
23 | |
24 | // OC0A is Output
|
25 | DDRB |= (1<<PB2); |
26 | |
27 | // Timer 1 Vorbereiten für Ein/Aus
|
28 | // Clear on Compare Match, Vorteiler 256
|
29 | TCCR1B = (1<<WGM12) | (1<<CS12); |
30 | |
31 | // Compare Match Interrupt an!
|
32 | TIMSK1 = (1<<OCIE1A); |
33 | |
34 | // Setze Compare Wert für genaue Sekunde
|
35 | OCR1A = 0x3BFF; |
36 | |
37 | |
38 | sei(); |
39 | |
40 | |
41 | |
42 | while (1) |
43 | {
|
44 | |
45 | |
46 | if (status==1) |
47 | {
|
48 | |
49 | // ADC holen, konvertieren und PWM einstellen
|
50 | MyADC = getADC(PWM); |
51 | |
52 | tast = convertADC(MyADC); |
53 | |
54 | SetPWM(tast); |
55 | |
56 | }
|
57 | else
|
58 | {
|
59 | // Schalte PWM ab!
|
60 | TCCR0A = 0; |
61 | }
|
62 | |
63 | |
64 | }
|
65 | |
66 | return 0; |
67 | }
|
und hier die Funktionen:
1 | uint16_t getADC(uint8_t mux) |
2 | {
|
3 | |
4 | // Kleinste gemessene Spannung 2,64 V
|
5 | |
6 | uint8_t i; |
7 | uint16_t result; |
8 | |
9 | ADMUX = mux; // Kanal waehlen |
10 | |
11 | |
12 | ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // Frequenzvorteiler |
13 | // setzen auf 32 (1) und ADC aktivieren (1)
|
14 | |
15 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
16 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
17 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
18 | while ( ADCSRA & (1<<ADSC) ) { |
19 | ; // auf Abschluss der Konvertierung warten |
20 | }
|
21 | result = ADCW; // ADCW muss einmal gelesen werden, |
22 | // sonst wird Ergebnis der nächsten Wandlung
|
23 | // nicht übernommen.
|
24 | |
25 | /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
|
26 | result = 0; |
27 | for( i=0; i<4; i++ ) |
28 | {
|
29 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
30 | while ( ADCSRA & (1<<ADSC) ) { |
31 | ; // auf Abschluss der Konvertierung warten |
32 | }
|
33 | result += ADCW; // Wandlungsergebnisse aufaddieren |
34 | }
|
35 | ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2) |
36 | |
37 | result /= 4; // Summe durch vier teilen = arithm. Mittelwert |
38 | |
39 | return result; |
40 | }
|
41 | |
42 | |
43 | |
44 | void SetPWM (uint8_t intense) |
45 | {
|
46 | |
47 | |
48 | |
49 | // Phase Correct PWM
|
50 | TCCR0A = (1<<COM0A1) | (1<<WGM00); |
51 | |
52 | // Clock / 64 = 121 Hz
|
53 | TCCR0B = (1<<CS01) | (1<<CS00); |
54 | |
55 | |
56 | //Tastverhältnis ändern
|
57 | OCR0A = intense; |
58 | |
59 | TIMSK0 = (1<<OCIE0A); |
60 | |
61 | sei(); |
62 | |
63 | }
|
64 | |
65 | |
66 | uint8_t convertADC(uint16_t MyADC) |
67 | {
|
68 | |
69 | uint16_t dummy16; |
70 | uint8_t dummy8; |
71 | |
72 | // Minimaler ADC wert in dieser Schaltung ist 490
|
73 | dummy16 = MyADC - 490; |
74 | |
75 | // Um eine 10er Potenz anheben
|
76 | dummy16 = dummy16*10; |
77 | |
78 | // So teilen, dass max. 255 herauskommen kann!
|
79 | dummy8 = dummy16 / 21; |
80 | |
81 | |
82 | return dummy8; |
83 | |
84 | }
|
Ich hab auch schon im Datenblatt geschaut - der richtige Interrupt Vector ist Vector 7 - das deckt sich mit den io files und stimmt. Warum geht das nicht? Kann jemand einen Fehler entdecken oder weiß jemand was ich falsch mache? Gruß Chris