PC to EUART on pic 16F688


Closed Thread
Results 1 to 11 of 11

Hybrid View

  1. #1
    Join Date
    Sep 2008
    Posts
    6


    Did you find this post helpful? Yes | No

    Default

    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

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    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

Similar Threads

  1. Replies: 24
    Last Post: - 2nd October 2017, 12:35
  2. Send data PIC to PC
    By konter in forum Off Topic
    Replies: 6
    Last Post: - 25th December 2009, 23:04
  3. Replies: 67
    Last Post: - 8th December 2009, 03:27
  4. HSERIN & Interupts (aka controlling PIC programs from a remote PC)
    By HankMcSpank in forum mel PIC BASIC Pro
    Replies: 16
    Last Post: - 17th June 2009, 15:46
  5. Replies: 11
    Last Post: - 12th July 2008, 03:36

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts