Bascom Timer richtig konfigurieren

AVRuser

Neues Mitglied
20. Apr. 2011
217
0
0
Niedersachsen
Sprachen
  1. BascomAVR
  2. ANSI C
Hallo Leute,

Wäre schön wenn mir jemand posten könnte, wie ich den Timer0 o. 2 so
konfiguriere, das er mir ungefähr alle 100µs einen Interrupt auslöst!

Ich verwende einen M1284p mit einem 16MHz Quarz...

Gruß:
AVRuser
 
Danke, dass keiner geantwortet hat;), hab durch viel googeln schon gefunden
was ich brauche, und es richtig verstanden!:rolleyes:

Gruß:
AVRuser
 
Es wäre interessant, wenn du hier die Lösung mal posten würdest. Es könnte ja sein, dass jemand ein ähnliches "Problem" hat.

Ansonsten muss man da gar nicht viel "googeln", sondern einfach mal in das Datenblatt schauen. Es ist sowieso immer wieder das selbe, bei allen AVRs. Und zum Berechnen des Comparewertes oder Nachladewertes hilft dann auch das Tool AVR-Timer-Calculator ein wenig.

Dirk
 
Da hier irgendwie 'ne Frage ohne Antwort steht - also um dem Thread 'n Sinn zu geben (und falls mal jemand sucht)... so in etwa würde ich das angehen:
- Die Main Clock läuft mit 16MHz - 16.000.000Hz, also Takte pro Sekunde
- Der IRQ soll alle 100µs erfolgen, also alle 0,1ms -> das entspricht einer Frequenz von 10.000Hz (10kHz)
- Folglich muß der IRQ also alle 16MHz / 10kHz = 1600 Main Clock Takte erfolgen
- Die geforderten Timer zählen als 8bitter nur von 0 bis 255 - folglich muß "vorgeteilt" werden
- Der Vorteiler muß mindestens 1600 / 256 = 6,25 betragen -> also Prescaler=8
- Somit läuft der Timer mit 16MHz / 8 = 2MHz, und würde mit einer Frequenz von 2MHz / 256 = 7,8kHz (ca.) überlaufen - folglich muß "oben was abgeschnitten werden"
- Timer in den CTC-Mode + Interrupt (welche da jetzt genau in Frage kommen, hab ich nicht durchgesehen, zumindest mit einem OCR sollte es gehen)
- Für 10kHz muß der Timer 2MHz / 10 kHz = 200 Takte durchlaufen.
- Somit sollte 199 in das entsprechende Compare Register geschrieben werden

Geht da irgendwer mit, oder hab ich mich schon wieder vertan?
 
Hallo Lotadac,

- Somit sollte 199 in das entsprechende Compare Register geschrieben werden

Geht da irgendwer mit, oder hab ich mich schon wieder vertan?

ja, das stimmt so. Nun hat der Thread ja wieder einen Sinn und er hilft auch vielleicht anderen Usern :)

timer_compare.png
 
Da hier irgendwie 'ne Frage ohne Antwort steht - also um dem Thread 'n Sinn zu geben (und falls mal jemand sucht)... so in etwa würde ich das angehen:
- Die Main Clock läuft mit 16MHz - 16.000.000Hz, also Takte pro Sekunde
- Der IRQ soll alle 100µs erfolgen, also alle 0,1ms -> das entspricht einer Frequenz von 10.000Hz (10kHz)
- Folglich muß der IRQ also alle 16MHz / 10kHz = 1600 Main Clock Takte erfolgen
- Die geforderten Timer zählen als 8bitter nur von 0 bis 255 - folglich muß "vorgeteilt" werden
- Der Vorteiler muß mindestens 1600 / 256 = 6,25 betragen -> also Prescaler=8
- Somit läuft der Timer mit 16MHz / 8 = 2MHz, und würde mit einer Frequenz von 2MHz / 256 = 7,8kHz (ca.) überlaufen - folglich muß "oben was abgeschnitten werden"
- Timer in den CTC-Mode + Interrupt (welche da jetzt genau in Frage kommen, hab ich nicht durchgesehen, zumindest mit einem OCR sollte es gehen)
- Für 10kHz muß der Timer 2MHz / 10 kHz = 200 Takte durchlaufen.
- Somit sollte 199 in das entsprechende Compare Register geschrieben werden

Geht da irgendwer mit, oder hab ich mich schon wieder vertan?

Hallo Lotadac,

es liegt schon paar Monate zurück....und heute mache ich mir Gedanken über diesen Thread.
Fast PWM .... Phase Correct PWM und CTC-Mod habe ich durchgekaut.
Es wird meine Aufgabe sein, diesen Text in einem Code umzuwandeln.

Hier ein Quelltext zum CTC - MOD2 vielleicht für Anfänger brauchbar.

Könnten Fehler in den Texten und der Programmstruktur vorhanden sein.

Code:
;Projekt: Projekttiny 13                        Datum: 13.04.2013

; Datei: CTC-MOD2-0A.asm

; Mode 2 = CTC (Takt nur für Outp. PB0=OC0A)   

; je kleiner der Wert im Compare-Reg. OCR0A, je höher die Frequ.

; Beispiel: 1,2MHz / 2 x N x (1+OCR0A) = 1,2/202 = 5,94 KHz
; N = Prescale im Beispiel 1

 ; sichtbares Impuls- Pausenverhältnis über Skop immer 1:1

 .include "tn13def.inc"

  .def   akku = r16

; Takt an PB0 (Pin OC0A) Periode = 0,168 ms 

  ldi    akku,(1<<COM0A0) | (1<<WGM01)
  out    TCCR0A,akku   

  ldi    akku,(1<<CS00)     ; no Prescale
  out    TCCR0B,akku

  .equ   Wert=100           ; Wert für OCR0A | an PB0 (OC0A)

  ldi    akku,(1<<PB1) | (1<<PB0)
  out    DDRB,akku          ; PB1+PB0 = Output

  ldi    akku,Wert          ; Wert für OCR0A laden  =100
  out    OCR0A,akku         ; und in Output Compare Register A laden

loop:    rjmp loop          ; Endlosschleife
 
.EXIT


Grüße

Rolf
 
Mal in Code-Tags setzen...
Code:
;Projekt: Projekttiny 13                        Datum: 13.04.2013
; Datei: CTC-MOD2-0A.asm
; Mode 2 = CTC (Takt nur für Outp. PB0=OC0A)   
; je kleiner der Wert im Compare-Reg. OCR0A, je höher die Frequ.
; Beispiel: 1,2MHz / 2 x N x (1+OCR0A) = 1,2/202 = 5,94 KHz
; N = Prescale im Beispiel 1
; sichtbares Impuls- Pausenverhältnis über Skop immer 1:1

 .include "tn13def.inc"
 .def   akku = r16

; Takt an PB0 (Pin OC0A) Periode = 0,168 ms 

  ldi    akku,(1<<COM0A0) | (1<<WGM01)
  out    TCCR0A,akku   

  ldi    akku,(1<<CS00)     ; no Prescale
  out    TCCR0B,akku

  .equ   Wert=100           ; Wert für OCR0A | an PB0 (OC0A)

  ldi    akku,(1<<PB1) | (1<<PB0)
  out    DDRB,akku          ; PB1+PB0 = Output

  ldi    akku,Wert          ; Wert für OCR0A laden  =100
  out    OCR0A,akku         ; und in Output Compare Register A laden

loop:    rjmp loop          ; Endlosschleife
 
.EXIT
Soll ich das jetzt kommentieren?
Als WGM hast Du CTC bis OCR0A gewählt (der 8-Bit-Timer läuft dann also im single-slope, aber eben nicht mehr von 255, sondern von OCR0A auf 0 über.)
Als COM für Kanal A hast Du toggeln bei compare match gewählt (was auch dem Überlaufpunkt entspricht). Deswegen auch das Puls-Pause-Verhältnis 1:1.
Der Timer ist mit Vorteiler=1 an den Systemtakt gekoppelt, läuft also effektiv mit Systemtakt.

Je größer der Teiler, desto langsamer der Timertakt. Desto kleiner die effektive Timerfrequenz, und somit auch die effektive Überlauffrequenz. Klar.
Je größer der OCR0A-Wert, desto weiter muß der Timer bis zu (jedem) Überlauf zählen. Also sinkt auch da die Überlauffrequenz.

Das alles geschieht komplett im Hintergrund (abgesehen von der Initialisierung). Den Controller selbst schickst Du danach in eine leere Endlosschleife (der tut nix mehr). Interrupts sind auch keine aktiviert...

Im Eröffnungspost war ja noch das Auslösen eines Interruptes gefordert - da würde sich hier der Output Compare Match A Interrupt anbieten.
Da Du mit dem CTC keinen(!) PWM gewählt hast, läßt sich Kanal B so auch nicht als PWM verwenden (Du kannst den Pin eben beim compare match setzen/löschen/toggeln lassen (ok, in Software könnte man die jeweilige komplementäre Aktion beim Überlauf (in der ISR) ausführen lassen, aber das ist dann halt kein reiner Hardware-PWM mehr).
Analog zum CTC kann der frequenzkorrekte fast-PWM (bis OCR0A) verwendet werden. Das ist WGM=7. Dann kann Kanal B als PWM verwendet werden, OCR0A legt dann mit dem Prescaler die PWM-Frequenz (=Timerüberlauffrequenz) fest, OCR0B den dutyCycle. Nebenbei kann der OCR0A-Interrupt dann in festen Intervallen Interrupts (Zeitbasis für Dein Hauptprogramm) erzeugen (falls man sowas braucht).

Fragen?...->...Fragen!
 
Mal in Code-Tags setzen...
Analog zum CTC kann der frequenzkorrekte fast-PWM (bis OCR0A) verwendet werden. Das ist WGM=7. Dann kann Kanal B als PWM verwendet werden, OCR0A legt dann mit dem Prescaler die PWM-Frequenz (=Timerüberlauffrequenz) fest, OCR0B den dutyCycle. Nebenbei kann der OCR0A-Interrupt dann in festen Intervallen Interrupts (Zeitbasis für Dein Hauptprogramm) erzeugen (falls man sowas braucht).

Fragen?...->...Fragen!

Hallo Lotadac,

danke für Deine Kommentierung!

Bin schon am grübeln, wie ich das hinbekomme.

Glaube, daß ich mit der Fast-PWM (Mod7) ansetzen werde.

Bei meinen Versuchen mit MOD3 konnte ich KanalA und B verwenden.

Jetzt muß ich dann WGM00 bis WGM02 setzen und verwende nur OCR0A.
Sobald die ersten Ergebnisse vorliegen, melde ich mich.

Grüße

Rolf
 
Irgendwie ist mir noch nicht so richtig klar, was Du (jetzt grad) erreichen/ausprobieren willst.
Generell kann der Timer im dual Slope (das sind die phasenkorrekten PWM) oder im single Slope (normal, CTC, fastPWM) laufen.
Es gibt 8bit oder 16bit-Timer (bei den AVR). Einige 16bit-Timer können auch als 9bit-oder 10bit-Timer verwendet werden (gibts 'nen WGM für) - Dein Tiny13 hat aber nur einen 8bitter.

Durch den Timertakt (über den Prescaler aus dem Systemtakt abgeleitet), bedingt sich also die ... ähm ... Überlauffrequenz/Periodenzeit... des Timers. Wenn man Zeiten erreichen will, die der Prescaler allein nicht erreicht, muß man den Timer eben weniger weit Zählen lassen/oben was abschneiden, klar?
Dazu muß der Timer also im Hintergrund ständig das erreichen dieses Punktes überprüfen. Und dann eben den Timer zurücksetzen/löschen (im singleSlope) bzw umkehren lassen (im dualSlope). Insbesondere muß also irgendwo der entsprechende Vergleichswert abgelegt sein. Dafür kann das OCRnA-Register (n=Timernummer) verwendet werden. Oder auch das ICRn-Register, falls der Timer über ein solches verfügt.
Durch die begrenzung der Reichweite kannst Du also die "Periodendauer" des Timers einstellen, die Überlauffrequenz sozusagen. Deswegen nenne ich diese Modi frequenzkorrekt. Der Tiny13 bietet dazu nur OCR0A an.

Normalmodus (WGM=0) -> CTC (WGM=2)
fastPWM (WGM=3) -> frequenzkorrekte fastPWM (WGM=7)
phasenkorrekte PWM (WGM=1) -> frequenz- und phasenkorrekte PWM (WGM=5)

Wenn OCR0A aber jetzt TOP definiert, schränkt das natürlich die normale Funktion des OC-Units (Kanal A) ein, ähnlich ist das mit dem InputCaptureUnit, wenn man das ICRn zur TOP-definition verwendet.

Im Normalmodus konntest Du beim match den Pin toggeln/setzen/löschen lassen. Das geht im CTC auch, nur daß der Timer jetzt auch gleich überläuft. MAX (255) wird nie erreicht, also auch kein Timerüberlaufinterrupt (im Normalmodus könnte man so einen SoftPWM realisieren).

Im fastPWM kannst Du du den Pin invertierend/nicht invertierend zappeln lassen (die jeweilige komplementäre Aktion wird automatisch bei TOP erledigt. Im frequenzkorrekten fastPWM ist jetzt aber OCR0A=TOP - beide Ereignisse treten quasi gleichzeitig auf, heben sich auf. Laut Fußnote wird das match ignoriert/nur die Aktion des Überlaufereignisses ausgeführt. Zusätzlich gibt es aber hier jetzt die Möglichkeit, den Pin beim Match (=Überlauf) zumindest toggeln zu lassen.

Im phasenkorrekten PWM gilt quasi dasselbe, nur eben mit den Unterschieden des dualSlopes.
 
Da hier irgendwie 'ne Frage ohne Antwort steht - also um dem Thread 'n Sinn zu geben (und falls mal jemand sucht)... so in etwa würde ich das angehen:
- Die Main Clock läuft mit 16MHz - 16.000.000Hz, also Takte pro Sekunde
- Der IRQ soll alle 100µs erfolgen, also alle 0,1ms -> das entspricht einer Frequenz von 10.000Hz (10kHz)
- Folglich muß der IRQ also alle 16MHz / 10kHz = 1600 Main Clock Takte erfolgen
- Die geforderten Timer zählen als 8bitter nur von 0 bis 255 - folglich muß "vorgeteilt" werden
- Der Vorteiler muß mindestens 1600 / 256 = 6,25 betragen -> also Prescaler=8
- Somit läuft der Timer mit 16MHz / 8 = 2MHz, und würde mit einer Frequenz von 2MHz / 256 = 7,8kHz (ca.) überlaufen - folglich muß "oben was abgeschnitten werden"
- Timer in den CTC-Mode + Interrupt (welche da jetzt genau in Frage kommen, hab ich nicht durchgesehen, zumindest mit einem OCR sollte es gehen)
- Für 10kHz muß der Timer 2MHz / 10 kHz = 200 Takte durchlaufen.
- Somit sollte 199 in das entsprechende Compare Register geschrieben werden

Geht da irgendwer mit, oder hab ich mich schon wieder vertan?

mh....erreichen will ich, diese Antwort auf die Frage von AVRuser in einem Code umzuwandeln!
 
Achso... der TE wollte einfach nur alle 100µs einen Interrupt erzeugen (siehe das letzte Zitat). Insbesondere keine Interrupts (deswegen CTC statt fastPWM), und auch keine toggelnden Pins (also als CompareOutputMode die normale Pinfunktion behalten).

Wie man das dann berechnen kann, hatte ich ja beschrieben, Dirk hat es mit seinem Programm auch nochmal abgesegnet.

Was noch fehlt, ist die Aktivierung des entsprechendes Interruptes, sowie dessen eintrag in die Interruptvektortabelle und die Implementierung der Interruptserviceroutine.
Ich kenne jetzt Deine Kenntnisse bezüglich Interrupts nicht - da der Originaltopic ja eh irgendwie abgerissen ist, denke ich, daß wir hier ruhig weitermachen können. Ansonsten wird irgendein Mod das schon abtrennen...
Also frag ruhig, wenn Unklarheiten auftreten.

P.S.: bei meiner App sieht das dann so aus
Screenshot_2013-04-15-22-59-46.png
 
was meinst Du, sollte ich vielleicht einen neuen Thread eröffnen. Erinnere mich an Oldmax Worte "man solle es nicht in die
Länge ziehen"!
Ich bleibe erst mal beim Tiny 13-20PU mit seiner internen Taktfrequenz von 1,2 MHz (9,6 / 8).
 
...Ich bleibe erst mal beim Tiny 13-20PU mit seiner internen Taktfrequenz von 1,2 MHz (9,6 / 8).
Und willst mit dem jetzt was erreichen? Auch alle 100µs einen Interrupt auslösen lassen?
Vorweg was zu den beiden Modi (frequenzkorrekter "Normalmodus"=CTC und frequenzkorrekter fastPWM):
-beide sind single Slope
-bei keinem müssen die OC-Pins durch den Timer (automatisch) bedient werden
-koppelt man diese aber an den Timer, gibt es hier unterschiede (siehe Tabellen zu den compare output modes)
-beim frequenzkorrektem fastPWM wird beim compareMatch das TOV-flag des Timers gesetzt. Dadurch kann also beim nächsten Timer-Takt (=Überlauf auf TCNT=0) ein Interrupt ausgelöst werden. Beim CTC ist das nicht der Fall (TOV wird immer bei max=255 gesetzt). Allerdings läßt sich stattdessen bei beiden der Interrupt des Top-definierenden Registers verwenden (CompareMatch=InterruptFlag, nächster TimerTakt=Überlauf=Interrupt (wenn Freigegeben).
-In den PWM-Modi werden Veränderungen an den Output Compare Registern zwischengepuffert, und erst beim nächsten Timerüberlauf wirksam, bei Normal und CTC greifen Veränderungen sofort (man könnte also mehrere Matches innerhalb einer Timerperiode umsetzen).

Ok, Du hast statt 16 MHz 9,6MHz, und einen System-Vorteiler von 8 (dafür könnte man den Timer Vorteiler aus meiner Rechnung da oben weglassen, dann kommt's fast(*) hin. Da der Timer etwas langsamer läuft, ist ein kleineres Ergebnis als 199 für OCR0A zu erwarten - der Rechenweg ist ja derselbe, rechnen kannst Du selbst...

(*) naja... eher die Hälfte... aber das Prinzip sollte klar sein.

Hab grad mal bei meiner Android-App geschaut... hab keine 9,6MHz drin gehabt ... jetzt schon;)
Das Bild lad' ich aber noch nicht hoch...

Du hast noch nichts zu Deinen Kenntnissen bezüglich Interrupts gesagt...
 
so ich muß erst mal frische Luft schnappen. Gebe heute Abend paar Kommentare ab!

Code:
; Projekt-Name: Projekttiny13                      Datum: 17.04.2013                                

; Datei: konfigur01.asm

; Aufgabe: Periodendauer = 0,1ms mit Timer0

;Berechnung laut Datenblatt Seite 64

;f = Taktfrequ. / 2xNx (1+OCR0A) = 1,2MHz/ 2x64 = 9,38KHz

; AVR: Tiny13 - 20PU

 .INCLUDE   "tn13def.inc"   ; Deklaration für Tiny13
 .EQU       takt = 1200000  ; Systemtakt 1,2 MHz

 .cseg                   ;Programmspeicher
 .org 0                  ;ab Adresse 0
 
 .def    akku=r16
 
  rjmp    start            
 .ORG     OVF0addr       ; Interrupt-Vektor
 
start:     

  ldi     akku,(1<<PB0)          
  out     DDRB,akku      ;  PB0=Output
                                     
           
; Timer0 initialisieren:
  ldi     akku,(1<<CS00) ; no Prescale 
  out     TCCR0B,akku
           
  
; Konfigurieren CTC-Mod 2 (Takt an PB0 = OC0A)

  ldi     akku,(1<<COM0A0) | (1<<WGM01)
  out     TCCR0A,akku
  
 .equ     Wert=63         ; Messung am Skop= Pt ca. 100ys  
 
  ldi     akku,Wert
  out     OCR0A,akku       ; Wert ins Compare Reg. A laden
  
  loop:   rjmp Loop   
 
  .EXIT
 
Verwende mal bitte code-tags um Deinen Code rum (einfach den ganzen Code markieren, und dann den Code-Button ("#") drücken, oder erst den Button, und dann den Code zwischen die tags kopieren...

Dein Timer hat jetzt aber keine Periodendauer von 100µs, sondern eher von 50µs (genau genommen 53,33...µs - wenn man den internen Oszillator als Referenz verwendet.). Du toggelst bei jedem Überlauf das Beinchen, also ein Durchlauf->"hintoggeln", ein Durchlauf->"zurücktoggeln". Deswegen kommst Du so am Beinchen auf auf eine toggle-Periodenzeit von 100µs (rechnerisch 106,833...µs).
Klar, der Timer muß ja für eine volle Periode des Beinchens 2x überlaufen (das ist ja die 2 in der Formel).
Achso, Du kannst Die Formel natürlich auch nach OCR0A umstellen...

Noch einen Hinweis: indem Du CS00 in TCCR0B setzt, koppelst Du den Timer direkt an den Systemtakt (ganau genommen also Vorteiler=1). Ab diesem Moment läuft der Timer also. Danach veränderst/setzt Du aber noch den WGM und den COM(KanalA). Und OCR0A ist solange noch 0 (initial value).
Das heißt, Du stellst den Timer noch ein, während er bereits läuft. Soll OCR0A sehr klein gewählt werden, wird das erste Match nicht gefunden, da TCNT0 da eventuell schon vorbei ist, ehe Du OCR0A beschreibst.
Üblicherweise beschreibt man erst alle anderen Register, und startet als letztes den Timer durch beschreiben von TCCR0B
 
Code:
ldi akku,(1<<COM0A0) | (1<<WGM01)
 out TCCR0A,akku

 .equ Wert=63 ; Messung am Skop= Pt ca. 100ys 

ldi akku,Wert
 out OCR0A,akku ; Wert ins Compare Reg. A laden

 loop: rjmp Loop 

.EXIT

nur mal als Test!

Ich betrachte mir gerade das Timing Diagramm vom CTC MOD
auf Seite 64.
Stimmt...läuft der Timer hoch u. zu Null hat sich eine halbe Periode
gebildet.
Ich müßte das Ganze mal mit Fast PWM aufziehen, oder Interrupt.
 
So müßte es dann richtig sein!

Code:
; Konfigurieren CTC-Mod 2 (Takt an PB0 = OC0A)

  ldi     akku,(1<<COM0A0) | (1<<WGM01)
  out     TCCR0A,akku
  
  ldi     akku,(1<<CS00) ; no Prescale 
  out     TCCR0B,akku
 
 
 .equ     Wert=63        ; Messung am Skop= Pt ca. 100ys  
 
  ldi     akku,Wert
  out     OCR0A,akku     ; Wert ins Compare Reg. A lade

oder sollte der Eintrag ins Reg. TCCR0B nach dem OCR0A kommen?
Danke für Deine Hinweise...ich lerne immer mehr dazu.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)