Code:
list p=16f876a ; list directive to define processor !!!!!!! ÄNDERN !!!!!!!
#include <P16F876A.INC> ; processor specific variable definitions !!!!!!! ÄNDERN !!!!!!!
__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC !!!!!!! ODER HALT ANDERS !!!!!!!!
;*****************************************************************************
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;*****************************************************************************
; STATUS bit definitions
#define _C STATUS,0 ; für die Kurzschreibung von Bitprüfungen: "BTFSS _C"
#define _Z STATUS,2 ;
; Hardware signals definitions
#define AUX5 sta_ra,4 ; Taste
;***** KONSTANTEN
;Tastenauswertung
K_NONE EQU 0x00 ; nix
K_FUZZI EQU 0x01 ; unklar
K_CLICK EQU 0x02 ; kurz
K_PRESS EQU 0x03 ; lang
;***********
flax EQU 0x27 ; diverse Flags
sta_ra EQU 0x63 ; Binärstatus von Port A
iscr EQU 0x6B ; scratch in der ISR
mscr EQU 0x6C ; scratch in der main()
key_cnt EQU 0x6E ; Anz. ISR-Zyklen "Taste ununterbrochen LOW" (=aktiv)
key_evt EQU 0x6F ; erkanntes Tastenevent
;***** GLOBALE VARIABLEN 0x70..0x7F
x70 EQU 0x70 ;
x71 EQU 0x71 ;
x72 EQU 0x72 ;
x73 EQU 0x73 ;
x74 EQU 0x74 ;
x75 EQU 0x75 ;
x76 EQU 0x76 ;
x77 EQU 0x77 ;
x78 EQU 0x78 ;
x79 EQU 0x79 ;
dlycnt EQU 0x7A ; Delay-Restzyklen zu je 1ms
ticker EQU 0x7B ; virtuelle Unruh; immerzu in Bewegung
temp_w EQU 0x7C ; variable used for context saving
temp_status EQU 0x7D ; variable used for context saving
temp_pclath EQU 0x7E ; variable used for context saving
temp_fsr EQU 0x7F ; variable used for context saving
;**********************************************************************
;**********************************************************************
ORG 0x0000 ; Begin of 2k-Code Page #0 (1st)
; processor reset vector
;**********************************************************************
;**********************************************************************
nop ; nop required for icd
goto MAIN ; go to beginning of program
nop
nop
;**********************************************************************
;**********************************************************************
ORG 0x0004 ; interrupt vector location ***************** hierher wird bei ALLEN Interrupt Requests verzweigt ****************
;**********************************************************************
;**********************************************************************
;********** Kontext sichern **********
movwf temp_w ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf temp_status ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf temp_pclath ; save off contents of PCLATH register
movf FSR,w ;
movwf temp_fsr ;
; Lead-In
;bcf INTCON,GIE ; globales IRQ-Disable ;;; das geschieht schon automatisch bei der IRQ response
bcf STATUS,RP0 ;
bcf STATUS,RP1 ; Bank 0 als default
bcf PCLATH,4 ;
bcf PCLATH,3 ; Code Page #0
; Identifizierung der Quelle
btfsc INTCON,T0IF ; der Timer0 ?
goto ISR_TMR0 ;
btfsc PIR2,CCP2IF ; das CCP2-Modul ? Dummy zur Strukturdarstellung
goto ISR_CCP2 ;
btfsc INTCON,INTF ; externer INT ? Dummy zur Strukturdarstellung
goto ISR_INT ;
goto ISR_RESTORE ; !!! Fangleine !!! (gegen ungewollt aktive IRQs)
; ab hier die Service-Routinen für die verschiedenen IRQ-Quellen
;********** ISR für den Timer0-Interrupt
ISR_TMR0
; IRQ-flag löschen und preload
bcf INTCON,T0IF ; Timer0-IRQ
movlw d'8' ; 256-(250-2!) = 8 für 1000,0 Hz @ 16,00MHz !!! DIESEN WERT AUCH BEIM INIT IM HAUPTPROGRAMM SETZEN !!!
movwf TMR0 ; preload = verkürzter Anlauf zum nächsten Überlauf-IRQ
; Eingänge lesen
movf PORTA,w ;
movwf sta_ra ; Port A in Abbildvariable einlesen
ISR_TMR0_1 ; *********** ein paar kleine Anregungen **************
; Millisekunden-Eieruhr
movf dlycnt,f ; Z-Flag generieren
btfss STATUS,Z ;
decf dlycnt,f ; dekr., wenn nicht null (Z=0)
; Millisekunden-Ticker (= virtuelle Unruh)
incf ticker,f ;
; ***************** und hier wird es interessant für dich *******************
ISR_KEY
; Tastenauswertung
; Tastenstatus elektrisch
btfsc sta_ra,4 ; LOW-aktiv !
goto ISR_KEY_1 ; NICHT betätigt, also auswerten
incf key_cnt,f ; betätigt, also hochzählen
movlw d'255' ; Endanschlag
subwf key_cnt,w ;
btfsc STATUS,Z ; auf Gleichheit prüfen
decf key_cnt,f ; Zählerstand deckeln
goto ISR_KEY_TAIL ; und Schluss
ISR_KEY_1
; Ereignis-Erkennung
movlw d'20' ; Max-Wert für Prellen
subwf key_cnt,w ;
btfss STATUS,C ; überschritten ?
goto ISR_KEY_END ; NEIN, dann Schluss
movlw K_CLICK ; JA!
movwf key_evt ; reicht für ein CLICK
movlw d'150' ; Max-Wert für CLICK
subwf key_cnt,w ;
btfss STATUS,C ; überschritten ?
goto ISR_KEY_END ; NEIN, dann Schluss
movlw K_FUZZI ; JA!
movwf key_evt ; reicht für ein FUZZI
movlw d'250' ; Max-Wert für FUZZI
subwf key_cnt,w ;
btfss STATUS,C ; überschritten ?
goto ISR_KEY_END ; NEIN, dann Schluss
movlw K_PRESS ; JA!
movwf key_evt ; reicht für ein PRESS
ISR_KEY_END
clrf key_cnt ; Event oder Prellen detektiert, daher löschen
ISR_KEY_TAIL
goto ISR_RESTORE ; Ende der Serviceroutine für den Timer0-Interrupt
;********** ISR für den CCP2-Interrupt ********** das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
ISR_CCP2
; das wäre der CCP2-Interrupt - derzeit ohne Funktion
bcf PIR2,CCP2IF ; auslösendes Flag löschen
; !!!!!!!!! hier dazwischen gehört dein eigener Code !!!!!!!!!!!!!
goto ISR_RESTORE ;
;********** ISR für den externen INT-Eingang ********** das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
ISR_INT
; das wäre der externe INT-Eingang - derzeit ohne Funktion
bcf INTCON,INTF ; auslösendes Flag löschen
; !!!!!!!!! hier dazwischen gehört dein eigener Code !!!!!!!!!!!!!
goto ISR_RESTORE ;
ISR_RESTORE
; Kontext wiederherstellen
movf temp_fsr,w ;
movwf FSR ;
movf temp_pclath,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf temp_status,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf temp_w,f ; Kniff, um W zu laden, ohne den Status zu verändern !
swapf temp_w,w ; restore pre-isr W register contents
retfie ; return from interrupt (impliziert ein "bsf INTCON,GIE")
;**********************************************************************
MAIN ; Das Hauptprogramm
;**********************************************************************
clrf INTCON ; alle Interruptquellen sperren, alle IRQs verwerfen
; Timer0 konfigurieren
bsf STATUS,RP0 ; Bank 1
clrwdt ; WDT-Register und implizit Prescaler löschen, das gehört sich so!
movlw b'10000011' ; int sys clk, 1:16, prescale assg. to TMR0
movwf OPTION_REG ;
bcf STATUS,RP0 ; Bank 0
movlw d'8' ; Presetwert vgl. Timer0-ISR
movwf TMR0 ;
; Startzustände herstellen
movlw d'0' ;
movwf ticker ;
movwf flax ; acht Flag-Bits
movlw K_NONE ;
movwf key_evt ;
bsf STATUS,RP0 ; Bank 1
clrf PIE1 ;
clrf PIE2 ;
bcf STATUS,RP0 ; Bank 0
clrf PIR1 ;
clrf PIR2 ;
clrf INTCON ; alle Quellen und IRQs disablen/rücksetzen
; Interrupts enablen bzw. in Gang setzen
bsf INTCON,T0IE ; Timer 0 enable
bsf INTCON,PEIE ; Gruppe der Peripherals
bsf INTCON,GIE ; globales Enable
; !!!!!!!!! hier dazwischen gehört dei eigener Code !!!!!!!!!!!!!
; und hier endlich die Hauptprogrammschleife
LOOOP
; auf Event K_PRESS prüfen
movlw K_PRESS ;
subwf key_evt,w ;
btfsc STATUS,Z ;
incf tastenzaehler ;
pagesel LOOOP ;
goto LOOOP ;
;**********************************************************************
; wartet stur, bis die ISR den Zähler dlycnt bis Null heruntergezählt hat
******* Das ist das Gegenstück zur dlycnf-Manipulation in der ISR ****************
******* auch wieder nur als Anregung zu verstehen ****************
P0_IDLE
movwf dlycnt ; Delayzeit wird im W-Register geliefert
P0_IDLE_1
movf dlycnt,f ; zero flag generieren
btfss STATUS,Z ; bei Z=1 ausbrechen
goto P0_IDLE_1 ;
return ;
;**********************************************************************
;**********************************************************************
END ; directive 'end of program'
;**********************************************************************
Hoffentlich habe ich dich nicht unterschätzt; langweilen will ich dich damit nicht. Ich nehme an, daß du mit MPLAB arbeitest, dann wirst du vieles schon kennen. Wenn du konkrete Fragen hast zu meinen Konstrukten - immer raus damit.
Lesezeichen