Forum: Mikrocontroller und Digitale Elektronik Tiny2313 Frequenz ändern ohne Timer anzuhalten


von Stefan_KM (Gast)


Lesenswert?

Hallo.

Ich möchte mit meinem Tiny2313 ein Rechteck an OC1A ausgeben mit dem CTC 
Mode. Also kein PWM, kontinuierliches Rechteck.

Jetzt möchte ich im gleichmäßigem Abstand zwischen 3 Frequenzen 
umschalten:
Beispiel:

...10kHz -- 100ms -- 23kHz -- 100ms -- 35kHz -- 100ms -- 10kHz...

Die Einzelfrequenzen einzustellen ist kein Problem. Kann ich messen. 
Werden auch ausgegeben.
Auch das Umschalten funktioniert soweit, dann kann ich die 
Einzelfreuqenzen zwar nicht mehr messen, aber ich sehe mit einem Oszi, 
wie das Rechteck hin und her wackelt.

Jetzt habe ich das Problem, das der Timer anscheinend machmal stehen 
bleibt und das Rechteck wird kurz abgeschaltet. Das passiert auch recht 
zufällig, also kein Muster zu erkennen.

Wenn ich die Frequenz umstelle und das Register OCR1AH/OCR1AL mit dem 
entsprechenden Wert beschreibe, muss ich dann noch abwarten bis das 
Compare Flag gesetzt wird?
Oder muss ich auf ein anderes Flag warten bevor die Frequenz 
umgeschaltet werden kann.

Danke euch.

von Thomas E. (thomase)


Lesenswert?

Das Problem beim "fliegenden Wechsel" ist, daß beim Umschalten auf eine 
höhere Frequenz der Wert im Counter größer sein kann, als der neu 
eingestellte im OCR. Dann läuft der Timer einmal die große Runde.

Der aktuelle Wert im Timer Counter muß immer kleiner sein als der neue 
Wert im Register. Das lässt sich aber problemlos abfragen.

mfg.

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

warten brauchst du auf nichts, allerdings solltest du die Register 
(..H/..L) in der richtigen Reihenfolge beschreiben (wenn du in ASM 
programmierst). Im CTC-Mode kann beim umschalten natürlich ein Jitter 
entstehen.

> Jetzt habe ich das Problem, das der Timer anscheinend machmal stehen
> bleibt und das Rechteck wird kurz abgeschaltet.
wie lang ist kurz?

Sascha

von Stefan_KM (Gast)


Lesenswert?

Sascha Weber schrieb:
> wie lang ist kurz?

Ca. 500ms.

von Stefan_KM (Gast)


Lesenswert?

Thomas Eckmann:
> Der aktuelle Wert im Timer Counter muß immer kleiner sein als der neue
> Wert im Register. Das lässt sich aber problemlos abfragen.

Das werde ich mal noch einbauen.

Beim Beschreiben von H und L Register habe ich schon die Reihenfolge 
variiert. Aber ohne Erfolg. Liegt wohl daran, dass ich in C programmiert 
habe.

von spess53 (Gast)


Lesenswert?

Hi

Dann schreib die neuen Werte im OC-Interrupt.

MfG Spess

von Stefan_KM (Gast)


Lesenswert?

spess53 schrieb :
> Dann schreib die neuen Werte im OC-Interrupt.

Sorry, kannst du kurz erläutern was du damit meinst?

Danke

von spess53 (Gast)


Lesenswert?

Hi

>Sorry, kannst du kurz erläutern was du damit meinst?

Du aktivierst den OC1A-Interrupt. Wenn der neue Wert geladen werden soll 
setzt du ein Flag (Variable). In der Interruptroutine machst du 
sinngemäß folgendes:

  if flag (
    OCR1A = newOC
    flag löschen )

MfG Spess

von Thomas E. (thomase)


Lesenswert?

Stefan_KM schrieb:
> Liegt wohl daran, dass ich in C programmiert

Das liegt nicht an C, sondern daran, daß es egal ist.

mfg.

von Stefan_KM (Gast)


Lesenswert?

Hallo.

Ich habe den Timer 1 Interrupt aktiviert und folgende Routine 
geschrieben:

-----------------------------------------------------
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
 if (freq_flag)
  {
    OCR1AH=Tab_freqvalues[counter_freq]/256;   //Tabelle mit 
Frequenzwerten
    OCR1AL=Tab_freqvalues[counter_freq]%256;
    freq_flag=0;
    LED4=0;                     //schaltet eine LED ein, zur Kontrolle
  }
 else;

}

-----------------------------------------------------

an anderer Stelle im Programm passiert folgendes:
-----------------------------------------------------

......
counter_freq++;
if (counter_freq > 3) counter_freq=1;    // Obergrenze kontrollieren 
freq_flag=1;                             // nächste Freq. durch Timer1 
Int
while(freq_flag);               // warten bis Interrupt ausgelöst wird
......
-----------------------------------------------------

Freq_flag ist ein globale Variable. Mein counter_freq bestimmt den Wert 
aus einer Tabelle für die entsprechend neue Frequenz.
Es scheint so zu sein, dass das freq_flag nicht auf 1 gesetzt wird, 
sodass die entsprechende Routine in der Interrupt Routine nicht 
durchgeführt wird. Ich verstehe jedoch nicht wieso nicht.

Intterupt Initialisierung:

TIMSK=0x82;         // Aktivierung Interrupt für Timer 0 und Timer 1.

von Werner B. (werner-b)


Lesenswert?


von Peter D. (peda)


Lesenswert?

1
void set_pwm( uint16_t val )
2
{
3
  if( val < OCR1A ){
4
    TIFR = 1<<OCF1A;
5
    while( !(TIFR & 1<<OCF1A));
6
  }
7
  OCR1A = val;
8
}


Peter

von Stefan_KM (Gast)


Lesenswert?

Ok, Peter.

Kannst du das kurz erläutern?

Danke

von Stefan_KM (Gast)


Lesenswert?

@Peter:

Wie muss ich meinen Timer 1 konfiguriert haben? Im PWM Mode, oder geht 
auch im CTC Mode.

Im Moment habe ich den Timer 1 im CTC Mode eingestellt mit aktiviertem 
Compare Match Interrupt.
Und da funktioniert nicht so wie ich es mir vorstelle.

von Stefan_KM (Gast)


Lesenswert?

Es funktioniert jetzt. Danke 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.