How to use
At the start of your program include the file “BASIC_INTS.INC” then declare the interrupt source and handler as normal. Lastly at the beginning of the handler issue the new command SYSTEM_SAVE and at the end SYSTEM_RESTORE.
You can now use just about the full subset of Proton commands without the time and code overheads of the BASIC interrupt system.
The file down loadable is “BASIC_INTS.INC” . and below a demo of printing while in an interrupt routine, this file will run in ISIS on the PIC18_ALCD_VHB board.
Notes For the 16 series PIC® (18C/F…) and PROTON+ Version 3.03 onwards set the IDE highlight options for Macros to another setting than normal to highlight the new commands as such.
' Save ALL the compiler's SYSTEM variables and selected SFR registers before an interrupt, then restore them
'
' This allows a greater subset of BASIC commands within an interrupt handler
'
' For 16-bit core (18F) devices only. Using PROTON+ Version 3.03 Onwards.
'
' This program can be tested using the PIC18_ALCD_VHB file in the ISIS simulator.
'
Include "PROTON18_4.INC" ' Use the PROTON Dev board for the demonstration
REMINDERS = OFF
RESERVE_RAM 127 ' Reserve enough RAM at top of memory for a worse case scenario of ALL BANKA being used for system variables
REMINDERS = On
Dim COUNTS As Word SYSTEM
Dim COUNTS2 As Word SYSTEM
Symbol TIMER1 = TMR1L.Word ' Create a WORD variable from two hardware registers
Symbol TMR1IF = PIR1.0
Symbol GIE = INTCON.7
ON_HARDWARE_INTERRUPT GoTo INTERRUPT_HANDLER ' Point the interrupt vector to the subroutine "INTERRUPT_HANDLER"
'------------------------------------------------------------------------------------------------------
DelayMS 200 ' Wait for things to stabilise
GoTo OVER_INTERRUPT ' Jump over the interrupt subroutine
'------------------------------------------------------------------------------------------------------
' Macro to save the compiler's SYSTEM variables and selected SFR registers
SYSTEM_SAVE MACRO-
ASM-
; Context SAVE the essential registers
movff STATUS,_RAM_END ; Save the STATUS register
movff WREG,_RAM_END - 1 ; Save the WREG
movff BSR,_RAM_END - 2 ; Save the bank select register
movff FSR0L,_RAM_END - 3 ; Save low byte of FSR0
movff FSR0H,_RAM_END - 4 ; Save high byte of FSR0
movff FSR1L,_RAM_END - 5 ; Save low byte of FSR1
movff FSR1H,_RAM_END - 6 ; Save high byte of FSR1
movff FSR2L,_RAM_END - 7 ; Save low byte of FSR2
movff FSR2H,_RAM_END - 8 ; Save high byte of FSR2
movff PRODL,_RAM_END - 9 ; Save the multiply registers
movff PRODH,_RAM_END - 10 ; These require saving because the compiler uses them regularly.
movff TBLPTRL,_RAM_END - 11 ; Save the Table Pointer registers
movff TBLPTRH,_RAM_END - 12 ; These require saving because the compiler uses them regularly.
movff TABLAT,_RAM_END - 13 ; Save the code memory access register
; Save the compiler's SYSTEM variables
lfsr 0,_RAM_END - 14 ; Point FSR0 to the next available piece of memory in high RAM
lfsr 1,_SYSTEM_VARIABLE_COUNT - 1 ; Point FSR1 to the end of the SYSTEM variables in Access RAM
movlw _SYSTEM_VARIABLE_COUNT ; Form a loop for the amount of system variables used
movff POSTDEC1,POSTDEC0 ; Move the compiler's SYSTEM variables from Access RAM into high memory
decfsz WREG,F ; Decrement and skip if zero the variable counter
bra $ - 6 ; Keep placing variables until all done
VARIABLE _RAM_POINTER = (_RAM_END - 14) - _SYSTEM_VARIABLE_COUNT ; Point to the finishing point of the variable save
ENDASM-
ENDM
'------------------------------------------------------------------------------------------------------
' Macro to restore the compiler's SYSTEM variables and selected SFR registers
SYSTEM_RESTORE MACRO-
ASM-
; Restore the compiler's SYSTEM variables
lfsr 0,_RAM_END - 14 ; Point FSR0 to the start of the system variables stored in high memory
lfsr 1,_SYSTEM_VARIABLE_COUNT - 1 ; Point FSR1 to the end of the SYSTEM variables in Access RAM
movlw _SYSTEM_VARIABLE_COUNT ; Form a loop for the amount of system variables used
movff POSTDEC0,POSTDEC1 ; Move the compiler's SYSTEM variables from high memory into Access RAM
decfsz WREG,F ; Decrement and skip if zero the variable counter
bra $ - 6 ; Keep placing variables until all done
; Context RESTORE the essential registers and exit the interrupt
movff _RAM_END - 13,TABLAT ; Restore the TABLAT register
movff _RAM_END - 12,TBLPTRH ; Restore high byte of TBLPTR
movff _RAM_END - 11,TBLPTRL ; Restore low byte of TBLPTR
movff _RAM_END - 10,PRODH ; Restore high byte of PROD
movff _RAM_END - 9,PRODL ; Restore low byte of PROD
movff _RAM_END - 8,FSR2H ; Restore high byte of FSR2
movff _RAM_END - 7,FSR2L ; Restore low byte of FSR2
movff _RAM_END - 6,FSR1H ; Restore high byte of FSR1
movff _RAM_END - 5,FSR1L ; Restore low byte of FSR1
movff _RAM_END - 4,FSR0H ; Restore high byte of FSR0
movff _RAM_END - 3,FSR0L ; Restore low byte of FSR0
movff _RAM_END - 2,BSR ; Restore the bank select register
movff _RAM_END - 1,WREG ; Restore the WREG
movff _RAM_END,STATUS ; Restore the STATUS register
ENDASM-
ENDM
'------------------------------------------------------------------------------------------------------
' Interrupt service routine
INTERRUPT_HANDLER:
SYSTEM_SAVE ' Save the SYSTEM variables and selected SFR registers
RESET_BANK ' Reset the RAM banks first so we know where we are in RAM
'
' The body of the Interrupt routine goes here
'
Print At 2,1, "INTERRUPT ",Dec COUNTS2," " ' Display an incrementing counter on the LCD
Inc COUNTS2 ' Increment the counter
SYSTEM_RESTORE ' Restore the SYSTEM variables and selected SFR registers
Clear TMR1IF ' Clear the Timer1 interrupt flag
retfie ' Exit the interrupt
RESET_BANK ' Reset the RAM banks so the main program knows where it is in RAM
'------------------------------------------------------------------------------------------------------
' The MAIN DEMO PROGRAM LOOP STARTS HERE
OVER_INTERRUPT:
Cls ' Clear the LCD
COUNTS = 0 ' \
COUNTS2 = 0 ' / Reset the two counting variables
GIE = 0 ' Disable All Interrupts for now
T1CON = %00000001 ' Turn on Timer1, prescaler = 1:1
PIR1.0 = 0 ' Clear TMR1 interrupt flag
PIE1.0 = 1 ' Enable TMR1 as peripheral interrupt source
INTCON = %11000000 ' Enable global interrupts and peripheral interrupts
While 1 = 1 ' Create an infinite loop
PIE1.0 = 0 ' Disable the TMR1 interrupt while we print in the foreground
Print At 1,1,"FOREGROUND ",Dec COUNTS," " ' Display an incrementing counter on the LCD
PIE1.0 = 1 ' Re-enable the TMR1 interrupt
Inc COUNTS
DelayMS 300
Wend
'
' This allows a greater subset of BASIC commands within an interrupt handler
'
' For 16-bit core (18F) devices only. Using PROTON+ Version 3.03 Onwards.
'
' This program can be tested using the PIC18_ALCD_VHB file in the ISIS simulator.
'
Include "PROTON18_4.INC" ' Use the PROTON Dev board for the demonstration
REMINDERS = OFF
RESERVE_RAM 127 ' Reserve enough RAM at top of memory for a worse case scenario of ALL BANKA being used for system variables
REMINDERS = On
Dim COUNTS As Word SYSTEM
Dim COUNTS2 As Word SYSTEM
Symbol TIMER1 = TMR1L.Word ' Create a WORD variable from two hardware registers
Symbol TMR1IF = PIR1.0
Symbol GIE = INTCON.7
ON_HARDWARE_INTERRUPT GoTo INTERRUPT_HANDLER ' Point the interrupt vector to the subroutine "INTERRUPT_HANDLER"
'------------------------------------------------------------------------------------------------------
DelayMS 200 ' Wait for things to stabilise
GoTo OVER_INTERRUPT ' Jump over the interrupt subroutine
'------------------------------------------------------------------------------------------------------
' Macro to save the compiler's SYSTEM variables and selected SFR registers
SYSTEM_SAVE MACRO-
ASM-
; Context SAVE the essential registers
movff STATUS,_RAM_END ; Save the STATUS register
movff WREG,_RAM_END - 1 ; Save the WREG
movff BSR,_RAM_END - 2 ; Save the bank select register
movff FSR0L,_RAM_END - 3 ; Save low byte of FSR0
movff FSR0H,_RAM_END - 4 ; Save high byte of FSR0
movff FSR1L,_RAM_END - 5 ; Save low byte of FSR1
movff FSR1H,_RAM_END - 6 ; Save high byte of FSR1
movff FSR2L,_RAM_END - 7 ; Save low byte of FSR2
movff FSR2H,_RAM_END - 8 ; Save high byte of FSR2
movff PRODL,_RAM_END - 9 ; Save the multiply registers
movff PRODH,_RAM_END - 10 ; These require saving because the compiler uses them regularly.
movff TBLPTRL,_RAM_END - 11 ; Save the Table Pointer registers
movff TBLPTRH,_RAM_END - 12 ; These require saving because the compiler uses them regularly.
movff TABLAT,_RAM_END - 13 ; Save the code memory access register
; Save the compiler's SYSTEM variables
lfsr 0,_RAM_END - 14 ; Point FSR0 to the next available piece of memory in high RAM
lfsr 1,_SYSTEM_VARIABLE_COUNT - 1 ; Point FSR1 to the end of the SYSTEM variables in Access RAM
movlw _SYSTEM_VARIABLE_COUNT ; Form a loop for the amount of system variables used
movff POSTDEC1,POSTDEC0 ; Move the compiler's SYSTEM variables from Access RAM into high memory
decfsz WREG,F ; Decrement and skip if zero the variable counter
bra $ - 6 ; Keep placing variables until all done
VARIABLE _RAM_POINTER = (_RAM_END - 14) - _SYSTEM_VARIABLE_COUNT ; Point to the finishing point of the variable save
ENDASM-
ENDM
'------------------------------------------------------------------------------------------------------
' Macro to restore the compiler's SYSTEM variables and selected SFR registers
SYSTEM_RESTORE MACRO-
ASM-
; Restore the compiler's SYSTEM variables
lfsr 0,_RAM_END - 14 ; Point FSR0 to the start of the system variables stored in high memory
lfsr 1,_SYSTEM_VARIABLE_COUNT - 1 ; Point FSR1 to the end of the SYSTEM variables in Access RAM
movlw _SYSTEM_VARIABLE_COUNT ; Form a loop for the amount of system variables used
movff POSTDEC0,POSTDEC1 ; Move the compiler's SYSTEM variables from high memory into Access RAM
decfsz WREG,F ; Decrement and skip if zero the variable counter
bra $ - 6 ; Keep placing variables until all done
; Context RESTORE the essential registers and exit the interrupt
movff _RAM_END - 13,TABLAT ; Restore the TABLAT register
movff _RAM_END - 12,TBLPTRH ; Restore high byte of TBLPTR
movff _RAM_END - 11,TBLPTRL ; Restore low byte of TBLPTR
movff _RAM_END - 10,PRODH ; Restore high byte of PROD
movff _RAM_END - 9,PRODL ; Restore low byte of PROD
movff _RAM_END - 8,FSR2H ; Restore high byte of FSR2
movff _RAM_END - 7,FSR2L ; Restore low byte of FSR2
movff _RAM_END - 6,FSR1H ; Restore high byte of FSR1
movff _RAM_END - 5,FSR1L ; Restore low byte of FSR1
movff _RAM_END - 4,FSR0H ; Restore high byte of FSR0
movff _RAM_END - 3,FSR0L ; Restore low byte of FSR0
movff _RAM_END - 2,BSR ; Restore the bank select register
movff _RAM_END - 1,WREG ; Restore the WREG
movff _RAM_END,STATUS ; Restore the STATUS register
ENDASM-
ENDM
'------------------------------------------------------------------------------------------------------
' Interrupt service routine
INTERRUPT_HANDLER:
SYSTEM_SAVE ' Save the SYSTEM variables and selected SFR registers
RESET_BANK ' Reset the RAM banks first so we know where we are in RAM
'
' The body of the Interrupt routine goes here
'
Print At 2,1, "INTERRUPT ",Dec COUNTS2," " ' Display an incrementing counter on the LCD
Inc COUNTS2 ' Increment the counter
SYSTEM_RESTORE ' Restore the SYSTEM variables and selected SFR registers
Clear TMR1IF ' Clear the Timer1 interrupt flag
retfie ' Exit the interrupt
RESET_BANK ' Reset the RAM banks so the main program knows where it is in RAM
'------------------------------------------------------------------------------------------------------
' The MAIN DEMO PROGRAM LOOP STARTS HERE
OVER_INTERRUPT:
Cls ' Clear the LCD
COUNTS = 0 ' \
COUNTS2 = 0 ' / Reset the two counting variables
GIE = 0 ' Disable All Interrupts for now
T1CON = %00000001 ' Turn on Timer1, prescaler = 1:1
PIR1.0 = 0 ' Clear TMR1 interrupt flag
PIE1.0 = 1 ' Enable TMR1 as peripheral interrupt source
INTCON = %11000000 ' Enable global interrupts and peripheral interrupts
While 1 = 1 ' Create an infinite loop
PIE1.0 = 0 ' Disable the TMR1 interrupt while we print in the foreground
Print At 1,1,"FOREGROUND ",Dec COUNTS," " ' Display an incrementing counter on the LCD
PIE1.0 = 1 ' Re-enable the TMR1 interrupt
Inc COUNTS
DelayMS 300
Wend


Menu
Recent Articles


Using PDS with SPI GLCD based on ST7565R Controller
Graphic LCDs based on the ST7565 are cheaper then GLCDs with other controllers. SPI requires only four pins. If the circuit