Written by Les Johnson 14th August 2007.
Code:
#Disable HRSIn, HRSINTO, HRSIN_RCREG_READ ' Disable the library subroutines for HRSIN with and without timeouts
'
' Create the SYSTEM variables and aliases for the Buffered commands
'
Dim GEN As Byte System ' \
Dim GENH As Byte System ' / Timeout value storage
Dim PP0 As Byte System ' \
Dim PP0H As Byte System ' / Storage for FSR0L\H registers
Dim PP1 As Byte System ' \
Dim PP1H As Byte System ' / Timeout inside loop counter
Dim _USART_TIMEOUT_INT As GEN
Dim _USART_TIMEOUT_INTH As GENH
Dim _USART_TIMEOUT_VALUE As _USART_TIMEOUT_INT.Word ' Alias the timeout value to GEN\H
Dim _FSR0_SAVE_INT As PP0
Dim _FSR0_SAVE_INTH As PP0H
Dim _USART_FSR0_SAVE As _FSR0_SAVE_INT.Word ' Alias the FSR0L\H storage to PP0\H
Dim _INSIDE_LOOP_INT As PP1
Dim _INSIDE_LOOP_INTH As PP1H
Dim _USART_INSIDE_LOOP As _INSIDE_LOOP_INTH.Word ' Alias the inside loop to PP1\H
Dim _USART_OUTSIDE_LOOP As PRODL.Word ' Alias the outside loop to PRODL\H registers
Dim _USART_FSR1_SAVE As Word System ' Storage for FSR1L\H registers
Dim _USART_INDEX_IN As Byte System ' Pointer to the next empty location in the buffer
Dim _USART_INDEX_OUT As Byte System ' Pointer to the location of the oldest character in the buffer
'
' Create the actual seriel buffer in high memory
'
Warnings = OFF
Reminders = OFF
RESERVE_RAM 100 ' Reserve some RAM at the top of memory as a serial buffer (MAX 255)
Symbol _USART_BUFFER_SIZE = __RESERVE_RAM_SIZE ' The amount of RAM reserved is the buffer size (MAX 255)
Dim _USART_RING_BUFFER[_USART_BUFFER_SIZE] As Byte At __START_OF_RESERVE_RAM ' Array for holding received characters
Reminders = On
Warnings = On
Dim _USART_FSR0 As FSR0L.Word
Dim _USART_FSR1 As FSR1L.Word
'
' Point to the high priority hardware interrupt handler
'
On_Hardware_Interrupt GoTo _USART_HIGH_PRIOR_INTERRUPT
GoTo _OVER_USART_HANDLER ' Jump over the subroutines
Small_Micro_Model = On ' Tighten the ASM code even more
'-------------------------------------------------------------------------------
' USART1 ring buffer interrupt handler
'
' Input : Interrupt is triggered on reception of a byte from the USART
' Output : Array _USART_RING_BUFFER holds the characters received
' : Byte _USART_INDEX_IN points to the current location within the buffer
' Notes : Does not indicate if an error occurs but does clear the error flags and carries on
'
_USART_HIGH_PRIOR_INTERRUPT:
If PIR1.5 = 1 Then ' Was it a USART1 byte Receive that triggered the interrupt ?
movlw 6 ' Yes. So Mask out unwanted bits
andwf RCSTA,W ' Check for errors
bnz _UART_ERROR ' Was either error status bit set?
_USART_FSR1_SAVE = _USART_FSR1 ' Save FSR1L\H registers
Inc _USART_INDEX_IN ' Move up the buffer
If _USART_INDEX_IN >= _USART_BUFFER_SIZE Then ' End of buffer reached ?
_USART_INDEX_IN = 0 ' Yes. So clear _USART_INDEX_IN
EndIf
_USART_FSR1 = VarPtr _USART_RING_BUFFER ' Point FSR1L\H to _USART_RING_BUFFER
_USART_FSR1 = _USART_FSR1 + _USART_INDEX_IN ' Add the buffer position to FSR1L\H
INDF1 = RCREG ' Place the received character into the buffer
_USART_FSR1 = _USART_FSR1_SAVE ' Restore FSR1L\H registers
retfie Fast ' Exit from the interrupt, restoring the WREG, STATUS, and BSR registers
_UART_ERROR:
Clear RCSTA.4 ' Clear receiver status
Set RCSTA.4
Else ' Otherwise...
' <<< Other Interrupt Conditions and Code here >>>
EndIf
retfie Fast ' Exit from the interrupt, restoring the WREG, STATUS, and BSR registers
'------------------------------------------------------------------------------
' Wait for a character from the interrupt driven circular buffer with timeout
'
' Input : GEN\GENH hold the timeout value in approx ms (0 to 65535)
' Output : PP0 and WREG hold the value received
' : CARRY Flag (STATUS.0) Clear if timeout out
' Notes : Uses PRODL\H as temporary variable storage
' : Uses FSR0L\H as buffer the pointer
'
#ifdef HRSINTO#REQ
HRSIN2:
@READ#BUFFER_REQ = 1 ; Enable the _USART_GET_CHAR subroutine
_USART_OUTSIDE_LOOP = _USART_TIMEOUT_VALUE ' Save the timeout value so it doesn't get overwritten
Clear _USART_INSIDE_LOOP ' Reset the inside loop counter
_USART_GETBUF_OUTSIDE:
Bra $ + 2 ' Delay for 2 cycles within the outside loop
_USART_GETBUF_INSIDE:
#ifdef WATCHDOG_REQ ' Delay for 1 cycle within the inside loop
clrwdt
#else
nop
#endif
movf _USART_INDEX_IN,W ' \
subwf _USART_INDEX_OUT,W ' / Is there anything in the serial buffer ?
bnz _USART_GET_CHAR ' Yes. So fetch it
WREG = 255 ' \
addwf _USART_INSIDE_LOOP,F ' \
Addwfc _USART_INSIDE_LOOPH,F ' Decrement the inside and outside loops
Addwfc _USART_OUTSIDE_LOOP,F ' /
Addwfc _USART_OUTSIDE_LOOPH,F ' /
btfss STATUS,C
ret ' Return with the CARRY flag clear to indicate timed out
Infsnz _USART_INSIDE_LOOP,W
incfsz _USART_INSIDE_LOOPH,W
Bra _USART_GETBUF_OUTSIDE
_USART_INSIDE_LOOP = ((59 * Xtal) / 4) ' Set the inside loop counter based upon the XTAL frequency
Bra _USART_GETBUF_INSIDE
#endif
'------------------------------------------------------------------------------
' Wait for a character from the interrupt driven circular buffer without timeout
'
' Input : None
' Output : WREG holds the value received
' Notes : Uses FSR0L\H as buffer pointers
'
#ifdef HRSINX#REQ
@HRSIN
@READ#BUFFER_REQ = 1 ; Enable the _USART_GET_CHAR subroutine
While _USART_INDEX_IN = _USART_INDEX_OUT ' Wait for a character to apear in the serial buffer
#ifdef WATCHDOG_REQ
clrwdt ' Clear the watchdog timer within the loop if required
#endif
Wend
#endif
' Fall through to _USART_GET_CHAR
'------------------------------------------------------------------------------
' Read a character from the interrupt driven circular buffer
'
' Input : None
' Output : WREG holds the value received
' Notes : Uses FSR0L\H as buffer pointers
'
#ifdef READ#BUFFER_REQ
_USART_GET_CHAR:
Inc _USART_INDEX_OUT ' Increment _USART_INDEX_OUT pointer (0 to 255)
If _USART_INDEX_OUT >= _USART_BUFFER_SIZE Then ' End of buffer reached ?
_USART_INDEX_OUT = 0 ' Yes. So clear _USART_INDEX_OUT.
EndIf
_USART_FSR0_SAVE = _USART_FSR0 ' Save FSR0L\H registers
_USART_FSR0 = VarPtr _USART_RING_BUFFER ' Point FSR0L\H to _USART_RING_BUFFER
_USART_FSR0 = _USART_FSR0 + _USART_INDEX_OUT ' Add the buffer position to FSR0L\H
WREG = INDF0 ' Read buffer location (_USART_INDEX_OUT) into WREG
PP0 = WREG ' Also place it into PP0
_USART_FSR0 = _USART_FSR0_SAVE ' Restore FSR0\H registers
bsf STATUS,C ' Set the CARRY flag to indicate a byte received
Return
#endif
'--------------------------------------------------------------------------------
' Initialise the USART1 interrupt
'
' Input : None
' Output : None
' Notes : Enables interrupt on USART1 receive.
' : Enables global and peripheral interrupts
' : If Prioritised interrupts are used, the USART interrupt priority is made high
'
INIT_USART_INTERRUPT Macro
GoSub _INIT_USART
Endm
#ifdef INIT_USART_INTERRUPT#REQ
_INIT_USART:
_USART_INDEX_IN = 0 ' Clear the buffer internal pointer
_USART_INDEX_OUT = 0 ' Clear the buffer external pointer
PIE1.5 = 1 ' Enable interrupt on USART1 receive
#ifdef __LOW_INTERRUPTS_ENABLED ' Are we using low priority interrupts as well ?
IPR1.5 = 1 ' Yes. So USART1 Receive Interrupt to High priority
#endif
INTCON = %11000000 ' Enable global and peripheral interrupts
Return
#endif
'--------------------------------------------------------------------------------
' Clear the Serial Buffer
'
' Input : None
' Output : None
' Notes : Also resets the index pointers to the serial buffer
'
CLEAR_SERIAL_BUFFER Macro
GoSub _CLEAR_USART_BUFFER
Endm
#ifdef CLEAR_SERIAL_BUFFER#REQ
_CLEAR_USART_BUFFER:
PIE1.5 = 0 ' Disable interrupt on USART1 receive
Clear _USART_RING_BUFFER ' Clear the serial buffer
_USART_INDEX_IN = 0 ' Clear the buffer internal pointer
_USART_INDEX_OUT = 0 ' Clear the buffer external pointer
PIE1.5 = 1 ' Re-Enable interrupt on USART1 receive
Return
#endif
Small_Micro_Model = OFF
_OVER_USART_HANDLER:


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