its always better to use the hardware than bit-banged routines and there is nothing better than a ring-buffer to overcome traffic snarls
Code:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Name : 16F690 LCD BACKPACK
' Date : oct 2025 richard
' Note : RING BUFFERED
' Notes : 19200 Intrc_OSC 8Mhz
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#CONFIG
cfg = _INTRC_OSC_NOCLKOUT
cfg&= _WDT_OFF
cfg&= _PWRTE_OFF
cfg&= _MCLRE_OFF
cfg&= _CP_OFF
cfg&= _CPD_OFF
cfg&= _BOD_OFF
cfg&= _IESO_OFF
cfg&= _FCMEN_OFF
__CONFIG cfg
#ENDCONFIG
DEFINE OSC 8
DEFINE INTHAND myint
ANSEL = 0 ' Set all pins digital
ANSELH = 0 ' Set all pins digital
OPTION_REG.7 = 0 ' PORTA/PORTB pull-ups are enabled by individual port latch values
CLEAR
DEFINE LCD_BITS 8 'defines the number of data interface lines (4 or 8)
DEFINE LCD_DREG PORTC 'defines the port where data lines are connected to
DEFINE LCD_RSREG PORTB 'defines the port where RS line is connected to
DEFINE LCD_RSBIT 6 'defines the pin where RS line is connected to
DEFINE LCD_EREG PORTB 'defines the port where E line is connected to
DEFINE LCD_EBIT 4 'defines the pin where E line is connected
DEFINE LCD_COMMANDUS 1500 'defines the delay after LCDOUT statement
DEFINE LCD_DATAUS 50 'delay in micro seconds
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $20 ' Enable transmit, BRGH = 0
SPBRG = 25 ' 19200 Baud @ 8MHz, 0.16%
SPBRGH = 0
BAUDCTL.3 = 1 ' Enable 16 bit baudrate generator
wsave VAR BYTE $70 SYSTEM ;wsave in access RAM
ssave VAR BYTE BANK0 SYSTEM
psave VAR BYTE BANK0 SYSTEM
index_in VAR BYTE bank0 ' Pointer - next empty location in buffer
index_out VAR BYTE bank0 ' Pointer - location of oldest character in buffer
errflag VAR BYTE bank0 ' Error flag
UartFlag VAR errflag.0
BufferFlag VAR errflag.1
buffer_size CON 32 ' Sets the size of the ring buffer
buffer VAR BYTE[buffer_size] ' Array variable for holding received characters
bufchar VAR BYTE ' Stores the character retrieved from the buffer
Bl var byte
GOTO overint ' Jump over the interrupt handler
ASM
myint
if CODE_SIZE <= 2 ; If less than 2K code space
; Save the state of critical registers (PIC12/PIC16)
movwf wsave ; Save W
swapf STATUS,W ; Swap STATUS to W (swap avoids changing STATUS)
clrf STATUS ; Clear STATUS
movwf ssave ; Save swapped STATUS
movf PCLATH,W ; Move PCLATH to W
movwf psave ; Save PCLATH
endif
; Check for hardware overrun error
btfsc RCSTA,OERR ; Check for usart overrun
goto usart_err ; jump to assembly error routine
; Test for buffer overrun
incf _index_in,W ; Increment index_in to W
subwf _index_out,W ; Subtract indexes to test for buffer overrun
btfsc STATUS,Z ; check for zero (index_in = index_out)
goto buffer_err ; jump to error routine if zero
; Increment the index_in pointer and reset it if it's outside the ring buffer
incf _index_in,F ; Increment index_in to index_in
movf _index_in,W ; Move new index_in to W
sublw _buffer_size-1; Subtract index_in from buffer_size-1
btfss STATUS, C ; If index_in => buffer_size
clrf _index_in ; Clear index_in
; Set FSR with the location of the next empty location in buffer
movlw _buffer ;Store the High byte of buffer to FSR
movwf FSR
addwf _index_in,W ; Add index_in to point to next empty slot
movwf FSR ; Store Low byte of pointer in FSR
; Read and store the character from the USART
movf RCREG,W ; Read the received character
movwf INDF ; Put the received character in FSR location
BTFSC PIR1,RCIF ;ANY MORE ?
goto myint
finished
; Restore the state of critical registers (PIC12/PIC16)
movf psave,W ; restore PCLATH
movwf PCLATH
swapf ssave,W ; restore STATUS
movwf STATUS
swapf wsave,F ; restore W (swap avoids changing STATUS)
swapf wsave,W
retfie ; Return from interrupt
; Error routines
buffer_err ; Jump here on buffer error
bsf _errflag,1 ; Set the buffer flag
usart_err ; Jump here on USART error
bsf _errflag,0 ; Set the USART flag
movf RCREG, W ; Trash the received character
goto finished ; Restore state and return to program
ENDASM
overint:
TRISC = 0
TRISB = % 10101111
TRISA = % 11111110
OSCCON = $70
PAUSE 500
hserout ["ready @19200"]
LCDOUT $FE,1
LCDOUT "ready @19200"
PAUSE 500
@ bsf LCD_RSREG ,LCD_RSBIT
INTCON = $C0
PIE1.5 = 1
GOSUB ERROR
main:
IF errflag Then GOSUB error ' Goto error routine if needed
IF index_in = index_out Then main ' loop if nothing in buffer
GoSub getbuf ' Get a character from buffer
' hserout [bufchar] ' Send the character to terminal
if bl then
if bufchar = 0 then
porta.0 = 0 ' Back Light OFF
endif
if bufchar = 8 then
porta.0 = 1 ' Back Light ON
endif
bl = 0
goto main
endif
if bufchar = 255 then
bl = 1
goto main
endif
if bufchar = 254 then
@ bcf LCD_RSREG ,LCD_RSBIT
goto main
endif
@ MOVE?BB _bufchar,R3
@ L?CALL lcdsend
@ bsf LCD_RSREG ,LCD_RSBIT
goto main ' loop back to top
error: ' Display error message
INTCON = 0 ' Disable interrupts while in the error routine
IF errflag.1 Then ' Determine the error
hserout ["B!",13]' Display buffer error on line-2
Else
hserout ["U!",13] ' Display usart error on line_2
EndIF
PIR1.5=0
errflag = 0 ' Reset the error flag ;clear any rcsta error
RCSTA.4=0 'CREN = 0 Disable continuous receive to clear hardware error
RCSTA.4=1 'CREN = 1 Enable continuous receive
INTCON = %11000000 ' Enable interrupts
RETURN ' repeat
getbuf: ' Move the next character in buffer to bufchar
index_out = index_out + 1 ' Increment index_out pointer (0 to 31)
IF index_out => buffer_size Then index_out = 0 ' Reset pointer if outside buffer
bufchar = buffer[index_out] ' Read buffer location(index_out)
Return
Bookmarks