Zwei Timer, die sich gegenseitig beeinflussen

Gast #2431777
Lesenswert?

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
Gast #2431797
Lesenswert?

@sei() : Oh, das vergaß ich zu entfernen beim Codepasten. Das hatte ich 
nur eingefügt zum Testen, als es ohne nicht ging. Ich wollte versuchen, 
verschachtelte Interrupts zu erlauben, aber das funktionierte nicht so 
richtig...
Gast #2431829
Lesenswert?

Ich hab jetzt beide Prescaler auf /8 gestellt, jetzt gehts besser. Ich 
habe jetzt Interrupts zum Zählen statt alle 4ms alle 1ms - das ist auch 
okay ;).

Trotzdem wundert mich, warum das Problem so auftrat und bin über jede 
Erhellung dankbar.

Grüße,
Lena

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