Comparewert über Interrupt ändern

easyphil

Neues Mitglied
18. Jan. 2011
19
0
0
36
A, A
Sprachen
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.
Könntet Ihr mir dabei vlt. helfen ?

Mit freundlichem Gruß
Phil

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
 
...
denke das hat was mit der Verzweigung im Interrupt zu tun.
...
Code:
...
PCI0addr_:
  push tmp1             ; Das SREG in tmp1 sichern. Vorher
  in   tmp1, SREG       ; muss natürlich tmp1 gesichert werden
  
  [B][Color=red]ldi  [/color][/B]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 
...
nicht der Vergleich selbst, aber dicht dran...
Du vergleichst hier 2 Konstanten miteinander, die sich natürlich nie ändern.
Du willst sicher statt der Registeradresse den Registerinhalt verwenden, oder?
 
Ja genau, also muss ich das wohl anders machen :rolleyes:

Jetzt kannst du mir bestimmt sagen wie? ^^

Bestimmt mit LDS?

... das wars :) danke für den Hinweis.

kann geschlossen werden. Falls es nicht noch ein paar Hinweise zur Verbesserung des Codes gibt.
 
kann geschlossen werden. Falls es nicht noch ein paar Hinweise zur Verbesserung des Codes gibt.

In der PinChange ISR sicherst du SREG im Register tmp1. Dieses überschreibst du aber gleich wieder. Wenn du mal im Hauptprogramm Code hast, kann es problematisch sein, wenn SREG durch eine ISR verändert wird. Das I Flag könnte auch verändert werden ;-)

Die Zeile mit BREQ benötigt du nicht.

Dirk :ciao:
 
...Jetzt kannst du mir bestimmt sagen wie? ^^

Bestimmt mit LDS?...
Kommt darauf an (hier wohl ja)
Normalerweise waren für die I/O-Register In/Out vorgesehen-damit können aber nur 5 bit adressiert werden. Als die Controller umfangreicher wurden (und die Register umsortiert/vereinheitlicht), reichte das nicht mehr, der ext. I/O wurde nötig. Da dieser aber nicht mehr von In/Out erreicht wird, er aber (wie auch die Rechenregister und der Standard I/O) in den SRAM eingeblendet ist (remapped), kannst Du auf diesen eben wie SRAM zugreifen...

LDS - Load Direct from Data Space
STS - Store direct To Data Space

LDI - LoaD Immediate

Alles klar?
 

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