Code:
'******************************************************************************
'* Name *
'* Compiler: PICBASIC PRO Compiler microEngineering Labs *
'* Author : Mike Tripoli *
'* Notes: Interrupt on Change (PORTB) ISR Routine *
'* Date : 04/02/2013 *
'******************************************************************************
; DEVICE USED = PIC16F1939
#config
__config _CONFIG1, _FOSC_INTOSC &_WDTE_OFF &_PWRTE_OFF &_MCLRE_ON &_CP_OFF &_CPD_OFF &_BOREN_OFF &_CLKOUTEN_ON &_IESO_OFF &_FCMEN_OFF
__config _CONFIG2, _WRT_OFF &_VCAPEN_OFF &_LVP_OFF &_STVREN_OFF &_PLLEN_OFF
#endconfig
DEFINE OSC 16 ; 16 mhz.
OSCCON = 111000 ; 16MHz, CLKOUT = 2MHz
; 1------- bit 7 = 1 PLL is on, bit7 = 0 PLL is off - i.e. bit7=1 then OSC is 4x WITH PLLEN_OFF
; -0010--- = 31.25 kHz MF 0011 =31.25 kHz HF(1) bit 6-3 IRCF<3:0>: Internal Oscillator Frequency Select bits 000x =31 kHz LF
; -0100--- = 62.5 kHz MF
; -0101--- = 125 kHz MF
; -0110--- = 250 kHz MF
; -0111--- = 500 kHz MF (default upon Reset) 1000 =125 kHz HF(1) 1001 =250 kHz HF(1) 1010 =500 kHz HF(1)
; -1011--- = 1 MHz HF
; -1100--- = 2 MHz HF
; -1101--- = 4 MHz HF
; -1110--- = 8 MHz or 32 MHz HF(see Section 5.2.2.1 “HFINTOSC”) 1111 = 16 MHz HF
; -1111--- = 16 MHz HF
; -xxxx0-- = bit 2 Unimplemented: Read as ‘0’
; ------1x = Internal oscillator block bit 1-0 SCS<1:0>: System Clock Select bits
; ------01 = Timer1 oscillator
; ------00 = Clock determined by FOSC<2:0> in Configuration Word 1
#HEADER
errorlevel -303 ; suppress Program word too large
#ENDHEADER
;VARIABLES
RB_COPY VAR BYTE
;ALIASES
;PORT CONTROL REGISTERS
;PORTA
TRISA = 111111 ; Set PORTA to all input
ANSELA = 000111 ; Set AN0-AN7 to digital with the exception of AN0-2
;PORTB
TRISB = 001111 ; Set PORTB.0-3 to all INPUTS
ANSELB = 000000 ; Set AN8 and higher channels to digital operation
IOCBN = 001111 ; TRIGGER ON NEGATIVE GOING EDGE
WPUB = 001111 ; RB.0-3 PULLUP - WPUB7 WPUB6 WPUB5 WPUB4 WPUB3 WPUB2 WPUB1 WPUB0
;PORTC
TRISC = 000000 ' Set PORTC to all output
;PORTD
TRISD = 000000
ANSELD = 000000 ; PortD outputs
;PORTE
TRISE = 111111
ANSELE = 000000
;ADC CONTROL REGISTERS
ADCON0 = 000000 ' ADC disabled, AN0 selected
ADCON1 = 010000 ' Clock Fosc/16 Should be 1uS
; X------- ADFM bit 7 1 = Right justified. 0 = Left justified, use ADRESH for data
; -XXX---- bit 6-4 ADCS<2:0>: A/D Conversion Clock Select bits
; 000 =FOSC/2
; 001 =FOSC/8
; 010 =FOSC/32
; 011 =FRC (clock supplied from a dedicated RC oscillator)
; 100 =FOSC/4
; 101 =FOSC/16
; 110 =FOSC/64
; 111 =FRC (clock supplied from a dedicated RC oscillator)
; ----X--- bit 3 Unimplemented: Read as ‘0’
; -----X-- bit 2 ADNREF: A/D Negative Voltage Reference Configuration bit
; 1 = VREF- is connected to external VREF- pin(1)
; 0 = VREF- is connected to VSS
; ------XX ADPREF<1:0>: Voltage Reference Configuration bits 1-0
; 11 = VREF+ is connected to internal Fixed Voltage Reference (FVR) module(1)
; 10 = VREF+ is connected to external VREF+ pin(1)
; 01 = Reserved
; 00 = VREF+ is connected to VDD
INTCON = 001000 ; INTERRUPTS ON, INTERRUPT ON CHANGE PORT RB
;bit 7 GIE: Global Interrupt Enable bit
;1 = Enables all active interrupts
;0 = Disables all interrupts
;bit 6 PEIE: Peripheral Interrupt Enable bit
;1 = Enables all active peripheral interrupts
;0 = Disables all peripheral interrupts
;bit 5 TMR0IE: Timer0 Overflow Interrupt Enable bit
;1 = Enables the Timer0 interrupt
;0 = Disables the Timer0 interrupt
;bit 4 INTE: INT External Interrupt Enable bit
;1 = Enables the INT external interrupt
;0 = Disables the INT external interrupt
;bit 3 IOCIE: Interrupt-on-Change Enable bit
;1 = Enables the interrupt-on-change
;0 = Disables the interrupt-on-change
;bit 2 TMR0IF: Timer0 Overflow Interrupt Flag bit
;1 = TMR0 register has overflowed
;0 = TMR0 register did not overflow
;bit 1 INTF: INT External Interrupt Flag bit
;1 = The INT external interrupt occurred
;0 = The INT external interrupt did not occur
;bit 0 IOCIF: Interrupt-on-Change Interrupt Flag bit
;1 = When at least one of the interrupt-on-change pins changed state
;0 = None of the interrupt-on-change pins have changed stat
;The IOCIF Flag bit is read-only and cleared when all the Interrupt-on-Change flags in the IOCBF register
;have been cleared by software.
OPTION_REG = 000011
; X------- bit 7 WPUEN: Weak Pull-up Enable bit 1 = All weak pull-ups are disabled (except MCLR, if it is enabled) 0 = Weak pull-ups are enabled by individual WPUx latch values
; -X------ bit 6 INTEDG: Interrupt Edge Select bit 1 = Interrupt on rising edge of INT pin 0 = Interrupt on falling edge of INT pin
; --X----- bit 5 TMR0CS: Timer0 Clock Source Select bit 1 = Transition on T0CKI pin 0 = Internal instruction cycle clock (FOSC/4)
; ---X---- bit 4 TMR0SE: Timer0 Source Edge Select bit 1 = Increment on high-to-low transition on T0CKI pin 0 = Increment on low-to-high transition on T0CKI pin
; ----X--- bit 3 PSA: Prescaler Assignment bit 1 = Prescaler is not assigned to the Timer0 module 0 = Prescaler is assigned to the Timer0 module
; -----XXX bit 2-0 PS<2:0>: Prescaler Rate Select bits
; 000 1 : 2 Bit Value Timer0 Rate
; 001 1 : 4
; 010 1 : 8
; 011 1 : 16
; 100 1 : 32
; 101 1 : 64
; 110 1 : 128
; 111 1 : 256
'Initialize registers and variables
rb_copy = 0 ; clear register to begin
PORTD = 0 ; ALL LEDS OFF TO START
goto start ; jump over interrupt
DEFINE INTHAND DO_RBPORT ; INTERRUPT HANDLER
asm
; BIG NOTE! THIS WORKS WITH "ENHANCED" PIC16F1xxx DEVICES. IF USED WITH OTHER DEVICES THEN
; YOU !!!MUST!!! DO CONTEXT SAVING YOURSELF!
DO_RBPORT
banksel INTCON ; SELECT INTCON BANK
bcf INTCON,7 ; clear INTCON GIE, disables interrupts
banksel IOCBF ; change to IOCBF bank
movf IOCBF,w ; copy IOCBF to W
movwf _RB_COPY ; copy W to RB_COPY (makes a copy of IOCBF)
banksel IOCBF
clrf IOCBF ; clear register to reset flags for new interrupts
btfsc _RB_COPY,0 ; TEST EACH BIT TO SEE WHICH BUTTON WAS PUSHED
goto _jump_0
btfsc _RB_COPY,1
goto _jump_1
btfsc _RB_COPY,2
goto _jump_2
btfsc _RB_COPY,3
goto _jump_3
; banksel INTCON ; switch to INTCON bank -NEVER GET HERE
; bsf INTCON,7 ; reset interrupts
endasm
start:
; INITIALIZE STUFF HERE IF NEEDED
mainloop:
Serout2 PORTD.7,84,[12] ; CLEAR THE OLED DISPLAY (www.seetron.com) AT BEGINNING
Serout2 PORTD.7,84,["MAINLOOP"] ; WRITE TEST TO OLED
inLoop:
high portd.0 ; do something main code body
pause 300
low portd.0
pause 300
goto inloop
; EACH "JUMP_x" REPRESENTS SEPERATE ROUTINES THAT RUN DEPENDING ON WHICH PUSHBUTTON IS PUSHED
jump_0:
pause 30 ; 30mS switch debounce - really crappy pushbuttons
PORTD = 0 ; TURN OFF ALL LEDS ON PORTD
INTCON.7 = 1 ; IMPORTANT: TURN INTERRUPTS BACK ON - NEVER DID IT IN ISR
Serout2 PORTD.7,84,[12] ; CLEAR THE OLED DISPLAY
Serout2 PORTD.7,84,["JUMP 0"] ;
j_0_loop:
high PORTD.0 ; TURN LED ON
pause 50 ; 50mS delay
low PORTD.0
pause 50
goto j_0_loop ; DO IT OVER AGAIN; COULD "GOTO" ANYWHERE
jump_1:
pause 30 ;
PORTD = 0
INTCON.7 = 1 ;
Serout2 PORTD.7,84,[12] ;
Serout2 PORTD.7,84,["JUMP 1"] ;
j_1_loop:
high PORTD.1
pause 100 ;
low PORTD.1
pause 100
goto j_1_loop
jump_2:
pause 30 ;
PORTD = 0
INTCON.7 = 1 ;
Serout2 PORTD.7,84,[12] ;
Serout2 PORTD.7,84,["JUMP 2"] ;
j_2_loop:
high PORTD.2
pause 150 ;
low PORTD.2
pause 150
goto j_2_loop
jump_3:
pause 30 ;
PORTD = 0
INTCON.7 = 1 ;
Serout2 PORTD.7,84,[12] ;
Serout2 PORTD.7,84,["JUMP 3"] ;
j_3_loop:
high PORTD.3
pause 200 ; 100mS delay
low PORTD.3
pause 200
goto j_3_loop
end
; W_OLED:
; HIGH PORTD.1
; INTCON.7 = 0 ; TURN INTERRUPTS OFF, WRITE TO OLED
; Serout2 PORTB.3,84,[12] ; CLEAR THE OLED DISPLAY AT BEGINNING 40.5mS TO DISPLAY THREE POT VALUES
; Serout2 PORTB.3,84,["ADC_0=",DEC3 ADC_0,13] ; Display adc channel 0
; Serout2 PORTB.3,84,["ADC_1=",DEC3 ADC_1,13] ; Display adc channel 0
; Serout2 PORTB.3,84,["ADC_2=",DEC3 ADC_2,13] ; Display adc channel 0
; Serout2 PORTD.0,84,[12] ; CLEAR THE OLED DISPLAY AT BEGINNING 40.5mS TO DISPLAY THREE POT VALUES
; Serout2 PORTD.0,84,["UPPER LIMIT=",DEC3 UPPER_LIMIT,13] ; Display adc channel 0
; Serout2 PORTD.0,84,["LOWER LIMIT=",DEC3 LOWER_LIMIT,13] ; Display adc channel 0
; PAUSE 5
; INTCON.7 = 1 ; TURN INTERRUPTS BACK ON
; LOW PORTD.1
; return
Bookmarks