PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Comparewert über Interrupt ändern



easyphil
27.02.2014, 14:59
Hallo liebe Gemeinde,

ich habe mal wieder ein Problem...
Was ich vor habe, ist bei jedem Flankenwechsel an PD2 die Frequenz von CP zu wechseln -->
OCR2A ändern. Das klappt auch, aber nur einmal. Also von 1MHz auf 500
kHz Leider klappt das nicht so ganz, ich
denke das hat was mit der Verzweigung im Interrupt zu tun. Ich habe
bereits probiert mit JMP und CPSE zu arbeiten und dann mittels JMP in
eine weiter-Subroutine zu springen. Ohne Erfolg.


#define fkHz 20000 ; Clock-Frequenz in kHz
#define fOCR2A 1000 ; 1 MHz: 1 us auf phiCP == OC2A
#define f1OCR2A 500 ; 0,5 MHz: 2 us auf phiCP == OC2A
#define c_OCR2A (fkHz/fOCR2A /2) -1 ; Comparewert für OCR2A => 9
#define c1_OCR2A (fkHz/f1OCR2A /2) -1 ; Comparewert1 für OCR2A => 19
#define phiSP_high 1 ; SP soll 1 Takt von CP High sein
#define phiSP_cnt 3000 ; nach 3000 Takten von CP soll neuer SP kommen
#define c_OCR1A phiSP_cnt -1 ; 1 Takt wird benötigt um SP zu HIGH zu schalten
#define c_OCR1B phiSP_cnt - phiSP_high -1 ; 1 Takt wird benötigt um SP wieder auf LOW zu setzen

.equ DDR_phiCP = DDRB ; Datadirectionregister von CP
.equ phiCP = 3 ; (PIN PB3 = CP) = Ausgang
.equ DDR_phiSP = DDRD ; Datadirectionregister von SP
.equ phiSP = 0 ; (PIN PD0 = SP) = Ausgang
.equ PORT_phiSP = PORTD ; Definiert den PORTD für SP um dort Werte zu setzen

.def tmp0 = r16 ; Tmp0 zum arbeiten definieren
.def tmp1 = r17 ; Tmp0 zum arbeiten definieren

;----------Interrupttable--------

.org $0000
rjmp reset
.org PCI0addr
rjmp PCI0addr_
.org OC1Aaddr
rjmp OC1Aaddr_
.org OC1Baddr
rjmp OC1Baddr_


;--------------------------------

;+++++++++++++++++Interrupthandler++++++++++++++++ ++++++

;----------SP- Erzeugung---------

; Bei erreichen des Vergleichswertes c_OCR1A wird folgender
; Interrupt ausgelöst:
OC1Aaddr_:
cbi PORT_phiSP,phiSP ; Bit in PORTD0 wird gelöscht
reti

; Bei erreichen des Vergleichswertes c_OCR1B wird folgender
; Interrupt ausgelöst:
OC1Baddr_:
sbi PORT_phiSP,phiSP ; Bit in PORTD0 wird gesetzt
reti
;--------------------------------

;-------Frequenzwechslung--------
; Bei jedem Flankenwechsel an PD2 soll die
; CP-Frequenz gewechselt werden
PCI0addr_:
push tmp1 ; Das SREG in tmp1 sichern. Vorher
in tmp1, SREG ; muss natürlich tmp1 gesichert werden

ldi tmp0,OCR2A
ldi tmp1,c1_OCR2A
CP tmp0,tmp1 ; Vergleiche Konstante mit Vergleichsregister
BRNE ungleich ; Wenn Ergebniss gleich überspringe das hier
BREQ istgleich ; Ergebniss war gleich

istgleich:
ldi tmp0,c_OCR2A ; Lade c1_OCR2A in tmp0
sts OCR2A,tmp0 ; speichere tmp0 in Vergleichsregister OCR2A
out SREG, tmp1 ; Die Register SREG und tmp1 wieder
pop tmp1 ; herstellen
reti

ungleich:
ldi tmp0,c1_OCR2A ; Lade c1_OCR2A in tmp0
sts OCR2A,tmp0 ; speichere tmp0 in Vergleichsregister OCR2A
out SREG, tmp1 ; Die Register SREG und tmp1 wieder
pop tmp1 ; herstellen
reti


;-------------------------------


;-------Bei Reset/Start µC------

reset:
ldi tmp0, LOW(RAMEND)
out SPL, tmp0
ldi tmp0, HIGH(RAMEND)
out SPH, tmp0


sbi DDR_phiCP,phiCP ; Setze Bit phiCP in DDR_phiCP DDRB=0b00001000
sbi DDR_phiSP,phiSP ; Setze Bit phiCP in DDR_phiCP DDRD=0b00000001

ldi tmp0,(1<<ISC00) ; Jeder Flankenwechsel löst INT aus [tmp0 = 0b00000001]
sts EICRA,tmp0 ; speichere tmp0 ins InterruptControlRegister EICRA
ldi tmp0,(1<<INT0) ; PD2 ist für Interrupt verantwortlich [tmp0 = 0b00000001]
out EIMSK,tmp0 ; speichere tmp0 ins InterruptMaskRegister EIMSK


; 8-Bit-Timer-2 (CP-Erzeugung)
ldi tmp0,c_OCR2A ; Lade c_OCR2A in tmp0
sts OCR2A,tmp0 ; speichere tmp0 in Vergleichsregister OCR2A
ldi tmp0,(1<<COM2A0)+(1<<WGM21) ; toggle OC2A, CTC per OCR2A [tmp0 = 0b01000010]
sts TCCR2A,tmp0 ; speichere tmp0 ins Controlregister TCCR2A
ldi tmp0,(1<<CS20) ; Prescaler = 1 [tmp0 = 0b00000001]
sts TCCR2B,tmp0 ; speichere tmp0 ins Controlregister TCCR2B

; 16-Bit-Timer-1 (SP-Erzeugung)
ldi tmp0,high(c_OCR1A) ; Lade Highanteil c_OCR1A in tmp0
sts OCR1AH,tmp0 ; speichere tmp0 in Vergleichsregister OCR1AH
ldi tmp0,low(c_OCR1A) ; Lade Lowanteil c_OCR1A in tmp0
sts OCR1AL,tmp0 ; speichere tmp0 in Vergleichsregister OCR1AH
ldi tmp0,high(c_OCR1B) ; Lade Highanteil c_OCR1B in tmp0
sts OCR1BH,tmp0 ; speichere tmp0 in Vergleichsregister OCR1BH
ldi tmp0,low(c_OCR1B) ; Lade Lowanteil c_OCR1B in tmp0
sts OCR1BL,tmp0 ; speichere tmp0 in Vergleichsregister OCR1BH
ldi tmp0,(1<<WGM12)+(1<<CS12)+(1<<CS11) ; CTC per OCR1A, ext. T1 fallend
; [tmp0 = 0b00001110]
sts TCCR1B,tmp0 ; speichere tmp0 ins Controlregister TCCR1B
ldi tmp0,(1<<OCIE1B)+(1<<OCIE1A) ; Aktiviere Interrupts für Comparematch bei
; OCR1A & OCR1B [tmp0 = 0b00000110]
sts TIMSK1,tmp0 ; speichere tmp0 ins InterruptMaskRegister TIMSK1
sei ; Aktiviere Globale Interrupts

;----------------------------

;+++++++++++++++++++++++++++++++++++++++++++++++++ +++++

;-------Hauptschleife--------
main_loop:
rjmp main_loop

Könntet Ihr mir dabei vlt. helfen ?

Mit freundlichem Gruß
Phil

- - - Aktualisiert - - -

Kann geschlossen werden,

statt ldi tmp0,OCR2A
muss lds tmp0,OCR2A