Forum: Mikrocontroller und Digitale Elektronik Zwei Timer, die sich gegenseitig beeinflussen


von Lena (Gast)


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

von Peter D. (peda)


Lesenswert?

Lena schrieb:
> 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.

T0 hat doch 2 PWM-Ausgänge, damit gehts.


Peter

von holger (Gast)


Lesenswert?

>Ich schätze, dass sich die Interrupts irgendwie gegenseitig behakeln.

ISR (TIMER0_OVF_vect)
{
    sei();

Mach das sei() da weg.

von Lena (Gast)


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...

von Lena (Gast)


Lesenswert?

Peter Dannegger schrieb:
> T0 hat doch 2 PWM-Ausgänge, damit gehts.

Die Hardware ist jetzt allerdings schon fertig :-/.

von Lena (Gast)


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

von Peter D. (peda)


Lesenswert?

Nimm mal für den Piezo den CTC-Mode, dann hast Du keine 
Frequenzmodulation mehr durch den T2 Interrupt.


Peter

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.