wiebel
23.06.2007, 15:32
Ich bräuchte mal etwas Hilfe bei meinem Code.
Allen verfügbaren Tutorials zum trotz renn ich in grosse Probleme wenn ich mehr als einen Timer einsetzen möchte, und/oder mehr als einen Interrupt habe.
; Lazy Sine wave for the Butterfly
; Lookuptable for a quarter Sine wave
; Portb6 for an LED, right next to GND
; --- insert GPL here --- Wiebel, 2007
;
; timer2 interrupt behaves very badly, first for some time PWM at $(ff)
; then Sine uncorrelated to frequency of Timer2
.include "m169def.inc"
.def temp = r16
.def pow = r17
.def ACount = r18
.def BCount = r19
.def PCount = r20
.def state= r21
.def speed = r22
.def table = r0 ; Z points here, readout of table
.org 0x0000
rjmp main ; Reset Handler
.org PCINT0addr ; next, button support
reti
; rjmp button
;.org 0x0014
.org OC2addr ; Interrupt for the adjustable
;.org OVF2addr ; speed TIMER2
; reti
rjmp timer2_ctc
.org OVF1addr
reti
; rjmp timer1_overflow ; Timer Overflow Handler
.org OVF0addr
reti
; rjmp timer0_overflow
main:
clt
ldi temp, LOW(RAMEND) ; Stackpointer
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, 0 ; initializing I/O Pins
out DDRE, temp ; Input (Joystick right-left)
ldi temp, 1<<PORTB6 ; Output LED (also Joy up)
out DDRB, temp
; ldi temp, 0b00000010 ; TOIE0: Interrupt at Timer Overflow
; sts TIMSK0, temp
ldi temp, 0b00000010 ; Interupt on compare
sts TIMSK2, temp
; ldi temp, 1<<PCIE0 ; next
; sts EIMSK, temp
; ldi temp, $ff
; ldi temp, (1<<PCINT2) | (1<<PCINT3)
; sts PCMSK0, temp
; ldi temp, 1<<ISC00
; sts EICRA, temp
; initializing registers
clr ACount ; PWM / SINE rate (L) Counter
clr BCount ; Adjustable speed (H) Counter
; X/Y ??
clr state ; State machine q1-q2-q3-q4-
clr PCount ; bookkeeper for table qsin
clr pow ; PWM - duty cycle
ldi speed, $ff ; Adjustable Speed Value
ldi temp, 0b00000010|(1<<WGM21) ; divider | CTC mode
sts TCCR2a, temp
ldi temp,$3f ; compare value for CTC
sts OCR2A, temp
ldi temp, (1<<COM1B1) | (1<<WGM11) ; setting timer1 ...
; ldi temp, 0b00100010
sts TCCR1A, temp
ldi temp, (1<<WGM13) | (1<<WGM12) | (1<<CS10) ; ... at full speed
; ldi temp, 0b00011001
sts TCCR1B, temp
ldi temp, 0x00 ; setting the top value for counter1
sts ICR1H, temp ; for the Sine-Wave PWM
ldi temp, 0xff
sts ICR1L, temp
ldi ZH, high(qsin<<1) ; pointing to qsin:
ldi ZL, low(qsin<<1) ; quarter Sine lookup table
ldi temp, $ff ; initial PWM Level
sts OCR1BL, temp
ldi temp, $0
sts OCR1BH, temp
; sbi PORTB, 6 ; futile previous attempts
sei ; activate interupts
loop: rjmp loop ; well nothing here
timer2_ctc:
inc ACount ; loop to delay the actual reading
cpi ACount, $3F ; delay for * interupt events
brne out
clr ACount
; cp BCount, speed ; second for longer delays (4bit PWM)
; brlo bout ; or adjustable (via speed)
; clr BCount
inc PCount ; increment the bookkeeping
lpm
ldi pow, $7f ; ofFset for the full Sinewave
cpi state, 0 ; in which quadrant are we ?
breq q0
cpi state, 1
breq q1
cpi state, 2
breq q2
cpi state, 3
breq q3
ldi state, 0 ; reset the state machine
q0: ; 1st quadrant, forward, positive
add pow, table ; add value of table to the Offset
rjmp up
q1: ; 2nd Q, backward, positive
add pow, table
rjmp down
q2: ; 3rd Q, forward, negative
sub pow, table
rjmp up
q3: ; 4th Q, backward, negative
sub pow, table
rjmp down
up: ; moving Z forward
inc ZL
rjmp level
down: ; moving Z backward
dec ZL
rjmp level
level: ; setting the actual PWM level
sts OCR1BL, pow
cpi PCount, $1f ; have we reached the end of the Table?
brne out
inc state ; go to next quadrant
clr PCount ; reset bookkeeping
reti
;bout: ; to make BCount adjustable
; inc BCount
out:
reti
;button: ; next
;reti
; sbis PINE, PINE3
; ldi speed, $0
; sbis PINE, PINE2
; ldi speed, $0f
; sts OCR1BL, speed
; reti
qsin:
; .org FlashEND-(0xFF/2) ; need more information
; quarter Sine - 127*sin(n/32) - 32 Points -128 points per Sine
.db 0,6,13,19,26,32,38,44,50,56,62,67,73,78,83,87,92,9 6,100,104,107,111,114,117,119,121,123,124,126,126, 127,127
; .org FlashEND-(0xFF/2) ; need more information
; quarter Sine - 127*sin(pi*n/16) - 16 Points - 64 points per Sine
; .db 0,13,26,39,52,64,75,85,94,103,110,116,121,124,126, 127 ; 127*sin(pi*n/16)
; quarter Sine - 127*sin(n/32) - 32 Points -128 points per Sine
; .db 0,6,13,19,26,32,38,44,50,56,62,67,73,78,83,87,92,9 6,100,104,107,111,114,117,119,121,123,124,126,126, 127,127
Also angefangen hab ich mit dem Sinus Lookup der (geteilt durch ACount/BCount) direkt mit Timer1, der auch die PWM steuert, abgeklappert wird. Soweit so gut. Als ich versuchen wollte einen weiteren Interrupt für die Tasten zu implementieren fingen dei Probleme an. Der Timer1
Interrupt kam nicht mehr durch. Dann wollte ich erstmal eine eigene Timerbasis für die Lookuptable machen, um Interrupt events zu sparen (Vorteiler statt ACount/BCount) damit mehr Luft für die Tasten bleibt (später). Timer0 war der völlige Reinfall, beim aktivieren von Timer0 ging überhaupt nichts mehr.
Also versuche ich es gerade mit Timer2 da geht was aber nicht das was es soll.
Timer2 soll über ein Compare Event seinen Interrupt werfen, welcher das Auslesen der Lookuptable voran bringt, soweit die Theorie.
Praktisch geht beim Start meine LED auf 100% an und verweilt in dieser unglücklichen Situation solange Timer2 eben hochzählt (diese zeit kann ich über Vorteiler und ORC2A gut beeinflussen), dann geht er in den Sinus als ob es keinen Timer2 mehr geben würde, was ja eigentlich heißt das Timer1 immernoch weitertriggert.
Ich steh noch sehr am Anfang mit µC daher hab ich sicher irgendwas Grundlegendes mit dem Interruptvektor Verhunzt.
Wenn ein geworfener Interrupt nicht im Vektor steht (also kein reti) wird dann automatisch zum nächsten übergegagnen? Also wenn z.B. ein
INT0 ankommt aber PCINT2 erst im Vektor steht, wird dann PCINT1 ausgeführt?
Ich hab keine Ahnung was ich noch versuchen kann, hab schon alles Mögliche ausprobiert.
Den Code auch nochmal als URL(mit Highlighting)
http://nopaste.gamedev.pl/?id=655[/code]
PS: Sorry für das Crossposting, ich hoffe ihr seht mir das nach. ;) -> mikrocontroller.net
Allen verfügbaren Tutorials zum trotz renn ich in grosse Probleme wenn ich mehr als einen Timer einsetzen möchte, und/oder mehr als einen Interrupt habe.
; Lazy Sine wave for the Butterfly
; Lookuptable for a quarter Sine wave
; Portb6 for an LED, right next to GND
; --- insert GPL here --- Wiebel, 2007
;
; timer2 interrupt behaves very badly, first for some time PWM at $(ff)
; then Sine uncorrelated to frequency of Timer2
.include "m169def.inc"
.def temp = r16
.def pow = r17
.def ACount = r18
.def BCount = r19
.def PCount = r20
.def state= r21
.def speed = r22
.def table = r0 ; Z points here, readout of table
.org 0x0000
rjmp main ; Reset Handler
.org PCINT0addr ; next, button support
reti
; rjmp button
;.org 0x0014
.org OC2addr ; Interrupt for the adjustable
;.org OVF2addr ; speed TIMER2
; reti
rjmp timer2_ctc
.org OVF1addr
reti
; rjmp timer1_overflow ; Timer Overflow Handler
.org OVF0addr
reti
; rjmp timer0_overflow
main:
clt
ldi temp, LOW(RAMEND) ; Stackpointer
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, 0 ; initializing I/O Pins
out DDRE, temp ; Input (Joystick right-left)
ldi temp, 1<<PORTB6 ; Output LED (also Joy up)
out DDRB, temp
; ldi temp, 0b00000010 ; TOIE0: Interrupt at Timer Overflow
; sts TIMSK0, temp
ldi temp, 0b00000010 ; Interupt on compare
sts TIMSK2, temp
; ldi temp, 1<<PCIE0 ; next
; sts EIMSK, temp
; ldi temp, $ff
; ldi temp, (1<<PCINT2) | (1<<PCINT3)
; sts PCMSK0, temp
; ldi temp, 1<<ISC00
; sts EICRA, temp
; initializing registers
clr ACount ; PWM / SINE rate (L) Counter
clr BCount ; Adjustable speed (H) Counter
; X/Y ??
clr state ; State machine q1-q2-q3-q4-
clr PCount ; bookkeeper for table qsin
clr pow ; PWM - duty cycle
ldi speed, $ff ; Adjustable Speed Value
ldi temp, 0b00000010|(1<<WGM21) ; divider | CTC mode
sts TCCR2a, temp
ldi temp,$3f ; compare value for CTC
sts OCR2A, temp
ldi temp, (1<<COM1B1) | (1<<WGM11) ; setting timer1 ...
; ldi temp, 0b00100010
sts TCCR1A, temp
ldi temp, (1<<WGM13) | (1<<WGM12) | (1<<CS10) ; ... at full speed
; ldi temp, 0b00011001
sts TCCR1B, temp
ldi temp, 0x00 ; setting the top value for counter1
sts ICR1H, temp ; for the Sine-Wave PWM
ldi temp, 0xff
sts ICR1L, temp
ldi ZH, high(qsin<<1) ; pointing to qsin:
ldi ZL, low(qsin<<1) ; quarter Sine lookup table
ldi temp, $ff ; initial PWM Level
sts OCR1BL, temp
ldi temp, $0
sts OCR1BH, temp
; sbi PORTB, 6 ; futile previous attempts
sei ; activate interupts
loop: rjmp loop ; well nothing here
timer2_ctc:
inc ACount ; loop to delay the actual reading
cpi ACount, $3F ; delay for * interupt events
brne out
clr ACount
; cp BCount, speed ; second for longer delays (4bit PWM)
; brlo bout ; or adjustable (via speed)
; clr BCount
inc PCount ; increment the bookkeeping
lpm
ldi pow, $7f ; ofFset for the full Sinewave
cpi state, 0 ; in which quadrant are we ?
breq q0
cpi state, 1
breq q1
cpi state, 2
breq q2
cpi state, 3
breq q3
ldi state, 0 ; reset the state machine
q0: ; 1st quadrant, forward, positive
add pow, table ; add value of table to the Offset
rjmp up
q1: ; 2nd Q, backward, positive
add pow, table
rjmp down
q2: ; 3rd Q, forward, negative
sub pow, table
rjmp up
q3: ; 4th Q, backward, negative
sub pow, table
rjmp down
up: ; moving Z forward
inc ZL
rjmp level
down: ; moving Z backward
dec ZL
rjmp level
level: ; setting the actual PWM level
sts OCR1BL, pow
cpi PCount, $1f ; have we reached the end of the Table?
brne out
inc state ; go to next quadrant
clr PCount ; reset bookkeeping
reti
;bout: ; to make BCount adjustable
; inc BCount
out:
reti
;button: ; next
;reti
; sbis PINE, PINE3
; ldi speed, $0
; sbis PINE, PINE2
; ldi speed, $0f
; sts OCR1BL, speed
; reti
qsin:
; .org FlashEND-(0xFF/2) ; need more information
; quarter Sine - 127*sin(n/32) - 32 Points -128 points per Sine
.db 0,6,13,19,26,32,38,44,50,56,62,67,73,78,83,87,92,9 6,100,104,107,111,114,117,119,121,123,124,126,126, 127,127
; .org FlashEND-(0xFF/2) ; need more information
; quarter Sine - 127*sin(pi*n/16) - 16 Points - 64 points per Sine
; .db 0,13,26,39,52,64,75,85,94,103,110,116,121,124,126, 127 ; 127*sin(pi*n/16)
; quarter Sine - 127*sin(n/32) - 32 Points -128 points per Sine
; .db 0,6,13,19,26,32,38,44,50,56,62,67,73,78,83,87,92,9 6,100,104,107,111,114,117,119,121,123,124,126,126, 127,127
Also angefangen hab ich mit dem Sinus Lookup der (geteilt durch ACount/BCount) direkt mit Timer1, der auch die PWM steuert, abgeklappert wird. Soweit so gut. Als ich versuchen wollte einen weiteren Interrupt für die Tasten zu implementieren fingen dei Probleme an. Der Timer1
Interrupt kam nicht mehr durch. Dann wollte ich erstmal eine eigene Timerbasis für die Lookuptable machen, um Interrupt events zu sparen (Vorteiler statt ACount/BCount) damit mehr Luft für die Tasten bleibt (später). Timer0 war der völlige Reinfall, beim aktivieren von Timer0 ging überhaupt nichts mehr.
Also versuche ich es gerade mit Timer2 da geht was aber nicht das was es soll.
Timer2 soll über ein Compare Event seinen Interrupt werfen, welcher das Auslesen der Lookuptable voran bringt, soweit die Theorie.
Praktisch geht beim Start meine LED auf 100% an und verweilt in dieser unglücklichen Situation solange Timer2 eben hochzählt (diese zeit kann ich über Vorteiler und ORC2A gut beeinflussen), dann geht er in den Sinus als ob es keinen Timer2 mehr geben würde, was ja eigentlich heißt das Timer1 immernoch weitertriggert.
Ich steh noch sehr am Anfang mit µC daher hab ich sicher irgendwas Grundlegendes mit dem Interruptvektor Verhunzt.
Wenn ein geworfener Interrupt nicht im Vektor steht (also kein reti) wird dann automatisch zum nächsten übergegagnen? Also wenn z.B. ein
INT0 ankommt aber PCINT2 erst im Vektor steht, wird dann PCINT1 ausgeführt?
Ich hab keine Ahnung was ich noch versuchen kann, hab schon alles Mögliche ausprobiert.
Den Code auch nochmal als URL(mit Highlighting)
http://nopaste.gamedev.pl/?id=655[/code]
PS: Sorry für das Crossposting, ich hoffe ihr seht mir das nach. ;) -> mikrocontroller.net