ATtiny85 Habe Problem mit CTC Modus. Wird nicht richtig ausgeführt.

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • ATtiny85 Habe Problem mit CTC Modus. Wird nicht richtig ausgeführt.

      Hallo,

      Ich möchte den Attiny85 in den CTC versetzen, so dass am portb.3 das Pin eine Frequenz von ca 14 kHz ausgibt.
      Ich kann aus Gründen des Stromverbrauchs nur den internen 1 MHz Takt. verwenden.
      Laut der Beschreibung im Datenblatt auf Seite 72 und der Berechnungsformel, müssten ca.14 KHz rauskommen.
      Mir fiel auf, dass wenn ich das OCRA Register mit einem Wert oberhalb von 128 lade der CTC Mode funktioniert und die Werte dem der Formel entsprechen.
      Nur unterahalb geht da nichts.
      Ich habe auch den config Timer benutzt. Da das nicht funktionierte habe ich die Register Schritt für Schritt geladen.
      Aber jetzt habe ich dafür auch keine Erklärung mehr, was ich vergessen haben könnte.

      Vielleicht könnte mir jemand behilflich sein?

      Source Code

      1. $regfile = "ATTiny85.dat"
      2. Ddrb.3 = 1 'Augänge deklariert
      3. Ddrb.4 = 1
      4. 'Config Timer0 = Ctc , Prescale = 1 , Clear Timer = 1 ,
      5. Timsk = Bits(ocie0a) ' benutze Timer Counter Compare Match A Interrupt
      6. Tccr0a = Bits(wgm01) 'CTC Modus eingestellt
      7. Tccr0b = Bits(cs00) 'Keinen Teiler eingestellt
      8. Ocr0a = 35 'Register mit Wert 35 laden
      9. On Oc0a Ctc_isr 'Bezeichnung Compare Match A Interrupt-Routine
      10. Enable Oc0a
      11. Enable Interrupts
      12. '##############################Main###########################################
      13. Do
      14. Loop
      15. '#############################Main ENDE ####################################'
      16. Ctc_isr:
      17. Toggle Portb.3 'Signal an PorB:3 ausgeben
      18. Return
      Display All
      Danke.
    • Die Angabe der Taktfrequenz fehlt ($Crystal = 1000000).

      Und Zeile 1 (in deinem Code Zeile 7) muss so lauten:

      BASCOM Source Code

      1. Config Timer0 = Timer , Prescale = 1 , Clear_Timer = 1
      2. OCR0A = 35 'Register mit Wert 35 laden
      3. On OC0A CTC_ISR
      4. Enable OC0A
      5. Enable Interrupts
      Nach Simulator werden dann die Bits für Timer0 und den CTC Mode korrekt gesetzt. So sollte es also funktionieren.

      Es darf von den WGM0x-Bits nur WGM01 gesetzt sein. Das ist nach Tabelle "Modes of Operation" im Datenblatt der CTC-Mode.
      Das Bit wird schon durch das Attribut: 'CLEAR_TUMER = 1" gesetzt.
      Übrigens ist das ein Wort, da gehört ein Unterstrich dazwischen! (Siehe Codeexplorer).
    • Hallo Lutz,
      der CTC wird schon funktionieren, nur deine ISR wird nicht schnell genug aufgerufen.
      Mit OCR0A = 35 wird die ISR alle 36 Takte aufgerufen, der Sprung in und aus der ISR mit den Befehlen darin benötigt aber etwa 120 Takte. D.h. es gehen dir einige Interrupts verloren, folglich wird die Frequenz an PB.3 kleiner.
      Wenn du eine Ausgabe an einem Pin haben willst, die den 14KHz entspricht, dann geht das ganz einfach über OC0A, also bei dir PB.0. Wenn du allerdings die ISR mit 14KHz aufrufen willst, dann würde ich an deiner Stelle die Taktfrequenz des Controllers erhöhen.
    • Wenn ein Attiny 85 verwendet wird, warum dann nicht das spezielle Feature davon namens PLL benutzen?
      Okay, diese PLL steht nicht dem Prozessorttakt zur Verfügung, nur den Periferieeinheiten. Somit käme der Timer1 laut Datasheet in Frage. Der Timer müsste ohne Interrupts auskommen dürfen, denn sonst würde eine PLL keinen nennenswerten Sinn machen, wenn das schnellere Hardware-Timing durch Software in Interrupt-Form zunichte gemacht würde.

      Ich selbst habe es noch nicht näher untersucht, ausprobiert. Mich momentan nur an die Info PLL im Zusammenhang mit Timer 1 erinnert.
    • Franz wrote:

      Mit OCR0A = 35 wird die ISR alle 36 Takte aufgerufen, der Sprung in und aus der ISR mit den Befehlen darin benötigt aber etwa 120 Takte
      Das ist des Rätsels Lösung.

      Kommt halt drauf an, was @Lutz59 eigentlich erreichen will.

      Wenn es nur um eine Frequenzausgabe geht , die 14kHz betragen soll, kann man das auch von der Hardware alleine erledigen lassen (Ohne ISR).
      Dafür kann man Fast-PWM nutzen aber auch CTC-Timer (ohne Interrupt) mit Compare Match und Pin Toggeln lassen.
      Der Pin wird dann bereits von der Hardware getoggelt. Man braucht dann einen Überlauf mit 28kHz (2x 14kHz), so wie du es ja jetzt auch hast (OCR0A=35).

      Compare0A=35

      Config Timer0 = Timer , Prescale = 1 , Compare_A = Toggle , Clear_Timer = 1 ' CTC-Mode mit Compate-Match


      Braucht man eine ISR, die mir 14kHz aufgerufen werden soll (z.B. Signal sampeln), muss man die Laufzeit der ISR beachten.
      Um die Laufzeit zu verbessern, kann das in Assembler erreicht werden und NoSave bei On Interrupt verwenden. Wenn die Laufzeit noch immer zu lange ist, muss man den Takt erhöhen.

      Wie Franz schon schrieb ist es wichtig, dass die ISR abgearbeitet ist, bevor der nächste Interrupt ausgelöst wird. Sonst scheint der Controller zu Hängen, weil er nur noch mit den Interrupts beschäftigt ist.
    • bitlogger wrote:

      Wenn ein Attiny 85 verwendet wird, warum dann nicht das spezielle Feature davon namens PLL benutzen?
      Okay, diese PLL steht nicht dem Prozessorttakt zur Verfügung, nur den Periferieeinheiten. Somit käme der Timer1 laut Datasheet in Frage. Der Timer müsste ohne Interrupts auskommen dürfen, denn sonst würde eine PLL keinen nennenswerten Sinn machen, wenn das schnellere Hardware-Timing durch Software in Interrupt-Form zunichte gemacht würde.

      Ich selbst habe es noch nicht näher untersucht, ausprobiert. Mich momentan nur an die Info PLL im Zusammenhang mit Timer 1 erinnert.
      Doch, man kann die PLL verwenden. Zum Beispiel wenn man 16MHz braucht, ohne Quarz. War schon Thema hier im Forum.
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Danke Euch,

      die mir eine Antwort auf mein Problem gesendet haben.
      ich werde mal Eure Vorschläge ausprobieren.
      Naheres zum Programm:
      Ich speise den ATtiny85 nur aus einer CR2032 Li Zelle und kann wegen der sonst zu hohen Stromaufnahme nicht mit einem höheren Takt operieren.
      Ausserdem schalte ich die Frequenz, zu einem niedriegem Wert hin um.
      Deshalb die INT Routine. Die kleinste Frequenz ist dann 4 KHz.
      Mit 8MHz funktioniert das auch super. Nur halt mit 1 Mhz nicht. Der Unterschied im Stromverbrauch ist schon erheblich.
      Das mit dem Benutzen der PLL habe ich noch nie benutzt und habe keine Erfahrung damit. Und ich weiss nicht wie hoch der Stromverbrauch bei dieser Betriebsart liegt. Der Zeit bei 1 Mhz ca. 800µA und bei 8MHz bei 2,8mA im aktiven Modus.
      Da liegen bei der Nutzung der vorgegebenen LI Zelle, schon Welten da zwischen.

      Dank Euch Allen nochmals und werde jetzt mal Eure Vorschläge ausprobieren und mich melden.

      Grüsse und einen schönen Sonntag
      Lutz
    • Lutz59 wrote:

      Ausserdem schalte ich die Frequenz, zu einem niedriegem Wert hin um.
      Auch das würde ohne Int Routine funktionieren. Jedoch wenn pin B0 nicht benützt werden kann würde dieser Aufruf das ganze beschleunigen.(bis ca 40kHz)

      Source Code

      1. On Oc0a Ctc_isr nosave
      2. Ctc_isr:
      3. !sbis Portb,3
      4. !Jmp setzen
      5. !cbi portb,3
      6. !jmp fertig
      7. Setzen:
      8. !sbi portb,3
      9. Fertig:
      10. Return
      Display All
    • Lutz59 wrote:

      was ich vergessen haben könnte
      Es fehlen neben der Angabe der Taktfrequenz (Mitch64 schrieb es bereits) auch die Angabe der Stackwerte im Programm:

      $swstack = 32
      $hwstack = 32
      $framesize = 40

      Sind keine Angaben vorhanden, werden die im Menu hinterlegten Werte benutzt, die m.M.n. viel zu niedrig sind.
      Bei niedrigen Werten überschneiden sich Stack-Speicher und Variablen und es kommt zu unerwünschten Effekten.