I haven't tried the crystal yet, but after really simplifying the serout strings, everything works fine. No errors. Then when I added back the code that I took out to simplify things I start having problems again. It's the pauseus commands that give me problems since the pauses are between 1ms and 2ms to control two servos. I can't see any other way of receiving UART data and controlling two servos. I'm trying like crazy to avoid real interrupts and I'd prefer not to have to have another microcontroller. Any suggestions? The deletions are included here. It's the code in the main loop that I added back.
' 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)
LED VAR PORTC.2 ' Alias LED
LCD VAR PORTC.1 ' Alias for LCD
SERVO1 VAR PORTC.3 ' Alias Servo Port
SERVO2 VAR PORTC.0 ' Alias Servo Port
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
pw VAR WORD ' Pulse Width Variable
direction Var Byte ' Direction Variable
carnumber Var Byte ' Car # 1 through 8
carsteering Var byte ' Car Steering
carthrottle Var byte ' Car Throttle
index_in = 0
index_out = 0
i = 0
col = 1
pw = 1200 ' start servo at extreme left
direction = 1
LOW SERVO1
LOW SERVO2
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
' Main program starts here - blink an LED at 1Hz
loop: Disable
HIGH SERVO1
Pauseus pw
LOW SERVO1
HIGH SERVO2
Pauseus pw
LOW SERVO2
Enable
For i = 0 to 16 ' Delay for 16ms (16*1mS)
Pause 1 ' Use a short pause within a loop
Next i ' instead of one long pause
pause 16 ' set frequency to about 50 Hz
If direction=0 THEN
pw = pw - 5
ELSE
pw = pw + 5
ENDIF
if pw > 1800 then direction=0 ' at extreme right, turn CCW. 0 is for left
if pw < 1200 then direction=1 ' at extreme left, turn CW. 1 is for right
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
'SEROUT LCD,N9600,[#bufchar] ' Clear Screen
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,[#carnumber]
'SEROUT LCD,N9600,[$fe,$c0] ' Move to beginning of 2nd line
'SEROUT LCD,N9600,[#carsteering]
'SEROUT LCD,N9600,[$fe,$94] ' Move to beginning of 3rd line
'SEROUT LCD,N9600,[#carthrottle]
'SEROUT LCD,N9600,[$fe,$d4] ' Move to beginning of 4th line
'SEROUT LCD,N9600,["End of Data Stream"]
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,["B"]
Else
SEROUT LCD,N9600,["U"]
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
Bookmarks