Bascom Timer richtig konfigurieren

ich steh noch auf dem Schlauch und habe Probleme mit der ISR.

Giebt das Kuttelmuttel mit Interrupt + CTC-Mod ?
Studio4 zeigte keine Fehler!

Code:
; Projekt-Name: Projekttiny13                      Datum: 18.04.2013									

; Datei: Interrupt01.asm

; Periode von 0,1ms an PB0
; Berechnung: T=1/1,2 x 10-6 =0,833ys x 256 = 0,213ms
; um auf 1ms mit CTC Mod2 abkappen???

; AVR: ATTINY13-20PU 

           .INCLUDE   "tn13def.inc"  
           .EQU       takt = 1200000 ; Systemtakt 1,2 MHz
											
           .DEF    akku = r16        
           .DEF    temp1 = r17        
           
           rjmp    reset             ; Reseteinsprung
           .ORG    OVF0addr          ; Interrupt-Vektor
           rjmp    TIM0_OVF          ; Sprung zur ISR


reset:     ldi     akku,(1<<PB0)   
           out     DDRB,akku         ; PB0 = Output
                                     
; Timer0 initialisieren:
          
           ldi     akku,(1<<TOIE0)   ; Timer Overflow Interrupt einrichten
           out     TIMSK0,akku       
           sei                       ; Timer frei (im SREG-Register, Bit7)

; Konfigur. CTC-MOD2

           ldi     akku,(1<<COM0A0) | (1<<WGM01)
           out     TCCR0A,akku
           
           ldi     akku,(1<<CS00)    ; Prescale = 1
           out     TCCR0B,akku 
           
           .equ    Wert=150        ; nur mal als Test
           ldi     akku,Wert
           out     OCR0A,akku      
           

loop:        rjmp    loop

;Interrupt-ISR
TIM0_OVF:  push    r2
           in      r2,SREG
           dec     temp1            ; wenn r17 <>0
           brne    ende             ; dann raus  
           ldi     temp1,0x02   ; neu setzen  

ende:      out     SREG,r2
           pop     r2
           reti
           .EXIT
 
Hallo Leute,
es hat mir keine Ruhe gelassen, aber ich hab einfach mal was probiert.
Ich weiß, der loop-Ablauf mit der ISR ist noch katastrophal, Lotadac hätte alles in die ISR gestopft.
Oldmax wird wieder die Hände über den Kopf schlagen mit den Vermerk "den Rolf trau ich alles zu"!
Aber lasst mal...es läuft. Ich kann mit dem Inhalt vom Comp. A (OCR0A) oder Prescale die Periode
verändern.
Am Skop liegen bei einem Wert von 60 u. Prescale=1 genau 0,1ms an. Gebe ich Presc. 8 hatte ich 800ms

Code:
; Projekt-Name: Projekttiny13                      Datum: 18.04.2013									

; Datei: Interrupt03.asm

; Periode von 0,1ms an PB0
; Berechnung: T=1/1,2 x 10-6 =0,833ys x 256 = 0,213ms
; mit Compare A auf 100ys hingezogen (Wert=60)

; AVR: ATTINY13-20PU 

           .INCLUDE   "tn13def.inc"  
           .EQU       takt = 1200000 ; Systemtakt 1,2 MHz
											
           .DEF    akku = r16        
           .DEF    temp1 = r17        
           
           rjmp    reset             ; Reseteinsprung
           .ORG    OVF0addr          ; Interrupt-Vektor
           rjmp    TIM0_OVF          ; Sprung zur ISR


reset:     ldi     akku,(1<<PB0) | (1<<PB1)  
           out     DDRB,akku         ; PB0 = Output
                                     
; Timer0 initialisieren:
          
           ldi     akku,(1<<TOIE0)   ; Timer Overflow Interrupt einrichten
           out     TIMSK0,akku       
           sei                       ; Timer frei (im SREG-Register, Bit7)

; Konfigur. CTC-MOD2

           ldi     akku,(1<<COM0A0) | (1<<WGM01)
           out     TCCR0A,akku
           
           ldi     akku,(1<<CS00)  ; Prescale = 1
           out     TCCR0B,akku 
           
           .equ    Wert=60           ; gemessen=0,1ms
           ldi     akku,Wert
           out     OCR0A,akku      
           

loop:      rcall   zeit
           sbi     PORTB,PB0
           rcall   zeit
           cbi     PORTB,PB0
           rjmp    loop

zeit:      ldi     temp1,0x02     ; r17 = 0b0000 0010    
pause:
           tst     temp1
           brne    pause
           ret   

;Interrupt-ISR
TIM0_OVF:  push    r2
           in      r2,SREG
           dec     temp1            
           out     SREG,r2
           pop     r2
           reti
           .EXIT

Es ergeben sich aber noch Fragen über Fragen; es ist noch nicht der letzte Stand!
 
1.: Natürlich kannst Du die OCR auch verändern, während der Timer (bereits) läuft. Du mußt halt nur im Hinterkopf behalten, daß da bereits wirksame Werte in den Registern stehen. Die initiale 0 führt dazu, daß der Timer quasi sofort nach dem Start überläuft, und ggf auch einen Interrupt auslöst. Noch in der ISR läuft er dann schon das nächste mal über - das Interrupt-Flag ist als bereits beim Verlassen der ISR gesetzt. Es wird dann eine Instruktion ausdem Hauptprogramm abgearbeitet, danach wird der Interrupt wirksam, usw. Dabei werden sogar einige Interrupts (Überläufe) übersehen - irgendwann schafft das Hauptprogramm dann aber das umsetzen des OCR0A, und deine Perioden stimmen (mehr oder weniger) -> Wenns auf die erzeugte waveform ankommt, muß auch das OCR vor dem Start des Timers (also vor TCCRB) beschrieben werden. Wenn der Effekt nicht stört, eben nicht. Du bestimmst, was geschehen soll...
2.:Was man in die ISR packt, hängt davon ab, was sie leisten soll, klar. Benötigst Du Im Hauptprogramm für irgendwelche Sachen die Information, daß 'ne bestimmte Zeit um ist reicht es, hier nur ein flag zu setzen, ein Merker, 'ne Notiz. Du mußt halt bedenken, daß der Interrupt das Hauptprogramm blockiert. Andererseits kann diese ISR ja (normalerweise) selbst nicht unterbrochen werden, wenn man also dann zB eine empfangene Information (UART etc) schnell genug decodiert, und die Entsprechende Information an das Hauptprogramm weitergibt, geht das auch. Da wird auch jeder Programmierer seine eigenen Wege gehen...
3.: läuft Dein Timer in Wirklichkeit (immer noch) alle 50ms (ca. der rechnerisch-genaue Wert fürs OCR0A wäre 59) über. Jeder Überlauf erzeugt eine Flanke am Pin, einmal hoch, einmal runter. 2 Flanken bilden eine Periode am Pin. Der Timer läuft aber ... ähm .... mit jedem Überlauf einmal über = 1 Periode vom Timer.
Wenn Du in der TOV-ISR eine Variable inkrementierst, hast Du sowas wie 'ne Stopuhr (ohne stop, ok). Da Dein Timer aber eben nicht alle 100µs überläuft, sondern bereits alle 50µs, zählt die dann 20tel ms statt 10tel ms.
4.: Du hast den Timer als CTC (an OCR0A gekoppelt) in Betrieb. Desweiteren als COM für Kanal A toggeln bei match eingestellt, damit ist das Beinchen nicht mehr an das PORT-Register gekoppelt. Du kannst zwar das PORT-Register wirksam manipulieren, das hat aber keinen Einfluß auf das Beinchen - hier bestimmt der Timer. (Das DDR bleibt aber wirksam).
5.: was ist jetzt eigentlich das Ziel Deiner Hauptschleife (in Verbindung mit der TOV-ISR)? Abgesehen davon, daß Manipulationen am PORT-Register keine Auswirkung haben (siehe letzter Punkt)? Das Beinchen soll für 2 Timerdurchläufe hi gesetzt werden (100µs), dann für weitere 2 low (auch 100s)? Du mußt hier aber davon ausgehen, daß das Laden von 2 nach Temp1 im allgemeinen bei irgendeinem beliebigen TCNT-Wert erfolgt.
Einfacher wäre es, wenn Du in der ISR nur einen Merker, ein Flag setzt (da braucht man uU nicht mal das SREG sichern), In der Hauptschleife pollst Du dieses flag ("If flag=gesetzt then blabla"), und weißt im then-Fall, daß der Timer einmal durch ist, also 50µs um sind. Dort ist natürlich das Flag wieder zurückzusetzen. Außerdem setzen wir vorraus, das diese IF-Abfrge alle 50µs mindestens einmal ausgeführt wird (ansonsten stimmts nicht).

So, reicht erstmal...
 
5.: was ist jetzt eigentlich das Ziel Deiner Hauptschleife (in Verbindung mit der TOV-ISR)? Abgesehen davon, daß Manipulationen am PORT-Register keine Auswirkung haben (siehe letzter Punkt)? Das Beinchen soll für 2 Timerdurchläufe hi gesetzt werden (100µs), dann für weitere 2 low (auch 100s)? Du mußt hier aber davon ausgehen, daß das Laden von 2 nach Temp1 im allgemeinen bei irgendeinem beliebigen TCNT-Wert erfolgt.
Einfacher wäre es, wenn Du in der ISR nur einen Merker, ein Flag setzt (da braucht man uU nicht mal das SREG sichern), In der Hauptschleife pollst Du dieses flag ("If flag=gesetzt then blabla"), und weißt im then-Fall, daß der Timer einmal durch ist, also 50µs um sind. Dort ist natürlich das Flag wieder zurückzusetzen. Außerdem setzen wir vorraus, das diese IF-Abfrge alle 50µs mindestens einmal ausgeführt wird (ansonsten stimmts nicht).

So, reicht erstmal...



oh weia...jetzt wirds richtig kompliziert! Könntest Du mir nicht mal ausnahmsweise paar Code-Geschnipsel rüber schieben?

Ich habe alles mögliche in meinem Code verändert und dabei den Skop im Auge gehabt.

z. B. in zeit: ldi temp1, 0x02 bis 0xFF verändert....das interessierte die Periode 100ys überhaupt nicht.

oder die ganze Timer initialisierung (TIMSK0,akku und sei) gelöscht....keine Änderung.
Ich konnte die Periode verändern mit dem Wert in OCR0A oder Prescale und merkte, daß hier der CTC-Mode2
Priorität hatte. Ich hab mich also foppen lassen.
Ich wüßte jetzt keinen Weg mehr, wie Interrupt und CTC voneinander unabhängig laufen sollen.
D.h. verändern der Periode durch Prescale bzw. Wert im OCR0A bzw. in zeit: ldi temp1,0x02

Grüße erst mal und Danke für Deine Zeit für mich.

Rolf
 

Ü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)