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.

Code:
#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