Huhu ihr,
ich habe einen Atmega644 und verwende alle 3 Timer. Timer1 ist dabei nur
für PWM zuständig und macht auch keine Probleme. Timer2 wird verwendet
für eine Zeitmessung, und Timer0 verwende ich, um einen Piezo
anzusteuern und damit einen Ton auszugeben. Dafür kann ich leider keinen
PWM-Ausgang verwenden, weil ich den Piezo für größere Lautstärke im
Push-Pull-Modus ansteuern möchte.
Timer2 wird alle 4ms aufgerufen, sodass ich 250 Impulse pro Sekunde
zählen kann. Ich brauche das sowohl zum Zeit messen und anzeigen
(Sekunden), als auch um ein paar Messwerte nach der Zeit zu
differenzieren (Luftdruck: Wird ein Variometer fürs Gleitschirmfliegen).
Timer0 ist abhängig von der Frequenz, die auf den Piezo gegeben werden
soll. Aktives Warten fand ich dafür unschön.
Wenn Timer2 deaktiviert ist (im entsprechenden TIMSK-Register) ist der
Sound durch den Piezo rein und klar (soweit man das davon sagen kann) -
sobald ich Timer0 auch aktiviere wird es kratzig. Als ob die
Tonerzeugung unterbrochen würde, immer wieder kurz. Ich habe leider kein
Oszilloskop um es besser zu beschreiben.
Ich schätze, dass sich die Interrupts irgendwie gegenseitig behakeln.
Ich habe folgenden Code:
Timer-Initialisierung:
1 | inline void init_timer()
|
2 | {
|
3 | //Timer für das Piepsen
|
4 | TCCR0B |= (1<<CS01); //durch 8 teilen
|
5 |
|
6 | //Overflow Interrupt einschalten
|
7 | TIMSK0 |= (1<<TOIE0);
|
8 |
|
9 | //Timer vorbelegen
|
10 | TCNT0=(255);
|
11 | //Ende Timer für das Piepsen
|
12 |
|
13 | //Timer für die Uhr
|
14 | TCCR2B |= (1<<CS21) | (1<<CS20);
|
15 |
|
16 | TIMSK2 |= (1<<TOIE2);
|
17 |
|
18 | TCNT2 = (256 - 125);
|
19 | //Ende Timer für die Uhr
|
20 | }
|
ISRs:
1 | ISR (TIMER0_OVF_vect)
|
2 | {
|
3 | sei();
|
4 | TCNT0 = (255 - beeper1.beepFreq);
|
5 |
|
6 | if (beeper1.doBeep)
|
7 | {
|
8 | if (beeper1.isHigh)
|
9 | {
|
10 | PIEZO_PORT |= PIEZO_PIN1;
|
11 | PIEZO_PORT &= ~(PIEZO_PIN2);
|
12 | beeper1.isHigh = FALSE;
|
13 | }
|
14 | else
|
15 | {
|
16 | PIEZO_PORT |= PIEZO_PIN2;
|
17 | PIEZO_PORT &= ~(PIEZO_PIN1);
|
18 | beeper1.isHigh = TRUE;
|
19 | }
|
20 | }
|
21 | else
|
22 | {
|
23 | //Beide Pins LOW vom Piezo
|
24 | PIEZO_PORT &= ~(PIEZO_PIN1 | PIEZO_PIN2);
|
25 | }
|
26 | }
|
27 |
|
28 | //Timer2-Überlauf
|
29 | ISR (TIMER2_OVF_vect)
|
30 | {
|
31 | TCNT2=(256 - 125);
|
32 |
|
33 | //das hier ist ein uint32_t, den sollte man evtl noch iwie ATOMIC machen
|
34 | //sollte aber nicht das Problem sein
|
35 | time.secondpartCounter++;
|
36 | if ((time.secondpartCounter & 32l) == 32l) //alle 32 Schritte updaten
|
37 | time.timeUpdated = TRUE;//wird in der main() bearbeitet
|
38 | }
|
Wie krieg ich das hin, dass sich das nicht gegenseitig behakelt? Ich
würde ungern Interrupts unter den Tisch fallen lassen. So lang sind die
Routinen ja jetzt nicht...
Wie gesagt wird es ein Variometer fürs Gleitschirmfliegen. Höhe über
Luftdruck messen geht auch schon, nur das Piepsen nicht so recht.
Eigentlich verrückt, wo das doch einfacher sein sollte :-/.
Viele Grüße,
Lena