Quote Originally Posted by docaberle View Post
I haven't tried the crystal yet, but after really simplifying the serout strings, everything works fine.
You'd still be better off in the long run using a crystal/resonator...

It's the pauseus commands that give me problems since the pauses are between 1ms and 2ms to control two servos.
Then don't use 1ms-2ms pause's. Give the serial interrupt routine a chance to grab the byte even when there's a pause going on.

Code:
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>>2
        Pauseus (pw>>2)

        LOW SERVO1
        HIGH SERVO2
        Pauseus (pw>>2
        Pauseus (pw>>2)

        LOW SERVO2
        Enable
        For i = 0 to 1600	' Delay for 16ms (16*1mS)
	        Pauseus 10   	' 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