PC to EUART on pic 16F688
I'm transmitting 5 bytes of data at a time. Decimal 0,0,1,127,128. The data goes from a UART on a netburner card to the RX pin on a 16F688. About 50% of the time I get a USART Overrun error. In addition, the pic chip sometimes restarts up showing a buffer error.
I'm using the internal oscillator at 4MHz and running at 2400 baud. Wondering if anyone can identify an issue with my code. The data makes it through most of the time without trouble, but I'm not sending a lot of data and there are seconds between when I send another 5 bytes. Curious if my defines are ok also? The code is taken from the samples list online and modified slightly. The only odd things is I look through the buffer with each byte that is collected and look for the 0,0,1 bytes to be there. Then the next byte will be a steering value and the next a throttle value.
' PicBasic Pro program to demonstrate an interrupt-driven
' input buffer for Hserin using On Interrupt.
' Pin definitions compatible with LAB-X1 and PIC16F877
DEFINE HSER_RCSTA 90h 'SPEN=0, CREN=0
DEFINE HSER_TXSTA 20h 'BRGH=0, SYNC=0, TXEN=1
DEFINE HSER_BAUD 2400
SPBRG = 25 ' Set baud rate to 2400 for USART
Include "modedefs.bas"
RCIF VAR PIR1.5 ' Alias RCIF (USART Receive Interrupt Flag)
OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable)
LCD VAR PORTC.1 ' Alias for LCD
buffer_size CON 32 ' Sets the size of the ring buffer
buffer VAR BYTE[buffer_size] ' Array variable for holding received characters
index_in VAR BYTE ' Pointer - next empty location in buffer
index_out VAR BYTE ' Pointer - location of oldest character in buffer
bufchar VAR BYTE ' Stores the character retrieved from the buffer
i VAR BYTE ' loop counter
col VAR BYTE ' Stores location on LCD for text wrapping
errflag VAR BYTE ' Holds error flags
carsteering Var byte ' Car Steering
carthrottle Var byte ' Car Throttle
index_in = 0
index_out = 0
i = 0
SEROUT LCD,N9600,[$1b,$2a,$40] 'Set Backlight Brightness
SEROUT LCD,N9600,[$fe,1] ' Clear Screen
INTCON = %11000000 ' Enable interrupts
ON INTERRUPT GoTo serialin ' Declare interrupt handler routine
PIE1.5 = 1 ' Enable interrupt on USART
loop: ' Main program starts here - do nothing for now
display: ' dump the buffer to the LCD
IF errflag Then error ' Handle error if needed
IF index_in = index_out Then loop ' loop if nothing in buffer
GoSub getbuf ' Get a character from buffer
If (buffer[index_out-4] = 0) then
if (buffer[index_out-3] = 0) then
if (buffer[index_out-2] = 1) then
carsteering = buffer[index_out-1]
carthrottle = buffer[index_out]
SEROUT LCD,N9600,[$fe,1] ' Clear Screen
SEROUT LCD,N9600,["Car=1"]
SEROUT LCD,N9600,[$fe,$c0] ' Move to beginning of 2nd line
SEROUT LCD,N9600,["Steering=",#carsteering]
SEROUT LCD,N9600,[$fe,$94] ' Move to beginning of 3rd line
SEROUT LCD,N9600,["Throttle=",#carthrottle]
Endif
Endif
endif
GoTo display ' Check for more characters in buffer
' Subroutines
Disable ' Don't check for interrupts in this section
getbuf: ' move the next character in buffer to bufchar
index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
IF index_out > (buffer_size-1) Then index_out = 0 ' Reset pointer if outside of buffer
bufchar = buffer[index_out] ' Read buffer location
Return
error: ' Display error message if buffer has overrun
SEROUT LCD,N9600,[$fe,$d4] ' Move to beginning of 4th line
IF errflag.1 Then ' Determine the error
SEROUT LCD,N9600,["Buffer Overrun"]
Else
SEROUT LCD,N9600,["USART Overrun"]
EndIF
errflag = 0 ' Reset the error flag
CREN = 0 ' Disable continuous receive to clear overrun flag
CREN = 1 ' Enable continuous receive
GoTo display ' Carry on
' Interrupt handler
serialin: ' Buffer the character received
IF OERR Then usart_error ' Check for USART errors
index_in = (index_in + 1) ' Increment index_in pointer (0 to 63)
IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer
IF index_in = index_out Then buffer_error ' Check for buffer overrun
HSerin [buffer[index_in]] ' Read USART and store character to next empty location
IF RCIF Then serialin ' Check for another character while we're here
Resume ' Return to program
buffer_error:
errflag.1 = 1 ' Set the error flag for software
' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag)
usart_error:
errflag.0 = 1 ' Set the error flag for hardware
Resume ' Return to program
End