Hi
Der Timer2 soll nach dem erreichen des gewünschten Wertes einen Interrupt auslösen.
Wie kann ich PEIE setzten?
Wie löse ich einen Interrupt aus?
Vielen Dank schon mal
MFG
EGSLER
Hi
Der Timer2 soll nach dem erreichen des gewünschten Wertes einen Interrupt auslösen.
Wie kann ich PEIE setzten?
Wie löse ich einen Interrupt aus?
Vielen Dank schon mal
MFG
EGSLER
Das Ein- / Ausschalten des peripheren und globalen Interrupts kann per DEFINEoder durch die BefehleCode:#DEFINE D_GlobIntEin bsf INTCON,GIE ; Globaler Interrupt Ein #DEFINE D_GlobIntAus bcf INTCON,GIE ; Globaler Interrupt Aus #DEFINE D_PeriIntEin bsf INTCON,PEIE ; Peripherer Interrupt Ein #DEFINE D_PeriIntAus bcf INTCON,PEIE ; Peripherer Interrupt Auserfolgen.Code:bsf INTCON,GIE ; Globaler Interrupt Ein bcf INTCON,GIE ; Globaler Interrupt Aus bsf INTCON,PEIE ; Peripherer Interrupt Ein bcf INTCON,PEIE ; Peripherer Interrupt Aus
Timer werden incrementiert / um 1 erhöht und setzen bei jedem Überlauf von 255 / 0xFF nach 0 das Interrupt-Flag T?IF. Diese Flags müssen per Software zurück gesetzt werden.
Wieviel Zeit zwischen jedem Timer-Increment vergeht, wird durch die Quarz-Frequenz und die Initialisierung der Prescaler bestimmt,
wie lange es bis zum Auslösen eines Interrupts dauert = 256 - Timer-Wert mal Increment-Zeit.
Zum Auslösen eines Interrupts / Aufruf der ISR (Interrupt-Service-Routine) muß das entsprechende IE-Flag und die globale Int-Freigabe GIE gesetzt sein. Für einige Timer muß zusätzlich die periphere Int-Freigabe PEIE gesetzt sein (im Datenblatt nachlesen).
In der ISR muß abgefragt werden, wer den Int ausgelöst hat.
MfG Karl-Heinz
HobbyElektronik hier klicken ....
Vielen Dank erstmal für die Antwort . Ich habe das Programm schon mal soweit aufgebaut, aber es scheint irgendwie nen Fehler zu haben, da es nicht aus der Schleife rausspringt . Vieleicht kannst du mir ja helfen den Fehler zu finden. MFG Nils (EGSLER)
;config
list p=16f628
#include <P16f628.INC>
__CONFIG _PWRTE_ON & _WDT_OFF & _HS_OSC & _LVP_OFF
;************************************************* *******
; Variablennamen vergeben
w_copy Equ 0x20 ; Backup für Akkuregister
s_copy Equ 0x21 ; Backup für Statusregister
;************************************************* *************
; los gehts mit dem Programm
org 0
goto Init
;************************************************* *************
; die Interruptserviceroutine
org 4
intvec bcf INTCON, GIE ; disable Interrupt
movwf w_copy ; w retten
swapf STATUS, w ; STATUS retten
movwf s_copy ;
movlw D'131' ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz)
movwf TMR2
; Intrrupt servic routine
Int_serv
incf PORTA, f
;hier folgt die eigentliche Interrupt-Routine,
;die 250 mal pro Sekunde aufgerufen wird
Int_end swapf s_copy, w ; STATUS zurück
movwf STATUS
swapf w_copy, f ; w zurück mit flags
swapf w_copy, w
bcf INTCON, PEIE ; Interrupt-Flag löschen
bsf INTCON, GIE ; enable Interrupt
retfie
;************************************************* *************
;Initialisierung am Anfang des Programms
Init
bsf STATUS, RP0 ; auf Bank 1 umschalten
movlw B'11110000' ; PortA RA0 output
movwf TRISA
bcf STATUS, RP0 ; auf Bank 0 zurückschalten
BSF CMCON, CM0 ;
Comparatoreingang auf Digital umschalten
BSF CMCON, CM1
BSF CMCON, CM2
; Vorteiler 16:1 und Timer2 einschalten
BSF T2CON,T2CKPS1 ; Vorteiler 16:1
BSF T2CON,TMR2ON ; Timer2 ein
; Frequenz auf 10 kHz einstellen
BSF STATUS,RP0 ; Bank1
MOVLW D'124'
MOVWF PR2 ; 2,5 kHz
BCF STATUS,RP0 ; Bank1
bsf INTCON, PEIE ;
bsf INTCON, GIE ; Interrupt erlauben
loop goto loop ; eine Endlosschleife
;************************************************* *********
end
Das GIE-Flag wird bei Auslösung eines Interrupts automatisch auf 0 und bei Verlassen durch RETI wieder auf 1 gesetzt; es sollte deshalb in der ISR nicht verändert werden.
Die xxIE-Flags (IE=Int-Enable) sollten auch nicht verändert werden.
bcf INTCON, PEIE ; Interrupt-Flag löschen
schaltet die peripheren Int's (dazu gehört vermutlich auch der benutzte Timer) am Ende der ISR aus !!!
Die xxIF-Flags (IF=Int-Flag) müssen in der ISR geprüft (wer hat ausgelöst) und vom Programm zurückgesetzt werden: bcf xxxxxxx, xxIF ; Interrupt-Flag löschen
MfG Karl-Heinz
HobbyElektronik hier klicken ....
Hallo EGSLER!
Dein Fehler ist im "Init" das mit endlose Schleife endet. Ein ASM Programm mit Interrupts, in dem ISR ein Hauptprogramm darstellt, sieht generell so aus:
org 0x0000
call Init
goto Main
org 0x0004
ISR...
retfie
Main goto Main
Init...
return
end
Siehe dazu "Interrupts" im "PIC Assembler" in Wiki.
MfG
@PICture
Was ist bei einem "goto Init" und abschließender Endlosschleife falsch ?
Nach der Interrupt-Freigabe wird alles in der InterruptServiceRoutine erledigt.
Init muß nicht zwingend als SubRoutine ausgeführt werden.
"Main" ist ein beliebiger LabelName, genau wie "loop".
Ich finde daran nichts falsch.
MfG Karl-Heinz
HobbyElektronik hier klicken ....
Hallo kalledom!
Sorry, es ist nichts falsch, ich habe bloss einen Fehler gesucht und nicht gefunden. Du hast recht, dass es egal ist, wo das Programm auf Interrupt wartet. Man weiss ja nicht was die eigentliche ISR machen sollte, die wurde leider nicht gepostet. Vielleicht tritt ein Interrupt ein und unterbricht die endlose Schleife, aber das ist nicht einfach festzustellen, wenn man nicht weiss, was geschiehen sollte. Ich gebe auf.
Schöne Grüsse!
Der Fehler wurde doch schon gefunden; EGSLER hat als vorletzten Befehl (vor reti) in der ISR:Damit wird aber nicht das Interrupt-Flag, sondern der Interrupt-Enabe für periphere Int's abgeschaltet.Code:bcf INTCON, PEIE ; Interrupt-Flag löschen
Da der Timer 2 beim PIC16F877 zu den peripheren Int's gehört, beim PIC16F628 sicherlich ebenso, wird nur 1 mal ein Int ausgelöst, weil dabei PEIE disabled wird .... dann kehrt Ruhe ein.
MfG Karl-Heinz
HobbyElektronik hier klicken ....
Lesezeichen