Hallo,
nach etwas genauerer Beschäftigung gebe ich den Vorrednern Recht - man gut mit PWM arbeiten. Ich habe mir nun überlegt den Timer mit dem IRQ im Vergleichs-Modus des Timers 2 laufen zu lassen. Ich habe dazu eine globale Variable definiert, die bei jedem IRQ herunter gezählt wird. Ist sie 0 wird der Timer2 und der IRQ ausgeschaltet.
Ich habe nur noch ein Problem mit der Tondauer. Übergebe ich sie in Sekunden funktioniert alles, Übergebe ich sie in Millisekunden höre ich nur einen kurzen Ton. Warum?
Hier mal der Code:
kann mir jemand erklären warum: Impulsanz_L = (2 * Ton * Zeit) / 1000;Code:/* TODO Der OC2 Port muss als Ausgang definiert werden Timer/Counter Control Register – TCCR2: Wir Wählen Mode 2 CTC also WGM21 (1) WGM20 (0) Wir benötigen den wechsel an OC2 also muss COM21 0 und COM20 1 sein Nun muss der Prescaler gesetzt werden. Table 54. Clock Select Bit Description CS22 CS21 CS20 Description 0 0 0 No clock source (Timer/Counter stopped). 0 0 1 clkT2S/(No prescaling) 0 1 0 clkT2S/8 (From prescaler) 0 1 1 clkT2S/32 (From prescaler) 1 0 0 clkT2S/64 (From prescaler) 1 0 1 clkT2S/128 (From prescaler) 1 1 0 clkT2S/256 (From prescaler) 1 1 1 clkT2S/1024 (From prescaler) Output Compare Register – OCR2 Hier setzen wir die Länge des Zählerveergleichs ein Die Quelle für den Takt des Timers lassen wir auf default Special Function IO Register – SFIOR brauchen wir nicht zu beachten Timer/Counter Interrupt Mask Register – TIMSK • Bit 7 – OCIE2 wird auf 1 gesetzt um den Interupt zu aktivieren, wenn der Vergleich stimmt (Compare) */ void Soundirq (unsigned int Ton, unsigned int Zeit) { unsigned int Impulsanz; unsigned long Impulsanz_L; unsigned int Laenge_L; unsigned char tmp_sreg; // temporaerer Speicher fuer das Statusregister des IRQ unsigned char Laenge; // Wie lange soll der Timer 2 zählen? /* Wenn ich mich nicht verrechnet habe ist bei 16 MHZ ein Prescaler von 1024 sinnvoll 16Mhz / 1024 = 15625 Hz Dies ist aber nur die doppelte Frequenz. Also kann der höchste Ton eine Frequenz von ca 7,8 kHz erreicht werden. Die niedrigste Frequenz ergibt sich aus diesem Wert durch 255 geteilt. Also ist der tiefste Ton also 30Hz Die Formel für die Länge des Comperatorregisters OCR2 ergibt sich: Laenge = f_quarz / (2* Ton * Prescaler) also ergibt sich mit den ausgerechneten Konstanten: Laenge = 7812 / Ton */ Laenge_L = 7812 / Ton; // Wie lang ist eine halbe Periodendauer Impulsanz_L = (2 * Ton * Zeit) / 1000; // Wieviele Interupte sind nötig Impulsanz = Impulsanz_L; Laenge = Laenge_L; TCCR2 |= (1 << WGM21) | (0 << WGM20) | (0 << COM21) | (1 << COM20); // Ein IRQ muss in einer Periode 2 mal ausgelöst werden DDRD |= (1 << DDD7); // Port D.7 auf Ausgang legen tmp_sreg = SREG; // Statusregister (also auch das IRQ-Flag darin) sichern cli(); // Interrupts global deaktivieren gSounddauer = Impulsanz; OCR2 = Laenge; TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20); // Prescaler auf 1024 setzen TIMSK |= (1 << OCIE2); // Timerinterupt einschalten SREG = tmp_sreg; // Status-Register wieder herstellen und auch das IRQ-Flag // auf gesicherten Zustand setzen sei(); // Interupt wieder einschalten - falls er nicht schon an war } /* Timer 2 ausschalten. Es werden keine Interupts durch ihn ausgelöst */ void Soundirq_aus(void) { unsigned char tmp_sreg; // temporaerer Speicher fuer das Statusregister tmp_sreg = SREG; // Statusregister (also auch das IRQ-Flag darin) sichern cli(); // Interrupts global deaktivieren TCCR2 = 0; // Timer 2 wird ausgeschaltet TIMSK &= (0 << OCIE2); // Timerinterupt ausschalten SREG = tmp_sreg; // Status-Register wieder herstellen und auch das IRQ-Flag // auf gesicherten Zustand setzen } /* Timer2 Compare Match IRQ Routine Wird benutzt um den Ton nur eine bestimme Zeit laufen zu lassen PWM möglich oder Port jeweils Invertieren */ ISR(TIMER2_COMP_vect) { if (gSounddauer > 1) { gSounddauer--; // Anzahl der Impulse veringern, so dass der Ton beendet wird //PORTD^=(1<<PD7); // invertiert Bit 7 an Port D (nichtnötig wenn PWM benutzt wird) } else { Soundirq_aus(); // Timer 2 ausschalten } }
ein falsches Ergebnis liefert?
Danke
Gruß
Stefan







Zitieren

Lesezeichen