1. We will be in Read Only mode (no new threads, replies, registration) starting at 9:00 EDT for a number of hours as we migrate the forums to upgraded software.

PIC 16F88 and RS-485

Discussion in 'Embedded Systems and Microcontrollers' started by Tekk, Apr 18, 2009.

  1. Tekk

    Thread Starter Member

    Apr 18, 2009
    Hi all,

    I'm designing a RS485 microcontroller system for an industrial application. I have a PIC 16F88 microcontroller and need it to

    A. listen on a RS485 network for a "#" symbol and then an address defined by a DIP switch connected to the PIC
    B. After the # and address, listen to the next byte
    and C. turn on LEDs on PORTB corresponding to the bits set in the RS485 byte.

    I understand I need a MAX485 or similar to do this.
    Can I just drive it with the 16F88's UART?
    What code would I need to do this?

    Thanks in advance,
  2. Tekk

    Thread Starter Member

    Apr 18, 2009
    Thanks for the welcome and fast reply.

    I will definitely follow your advice about the pass-byte and checking it against the DIP switch at power on, however I need to control 8 LEDs according to the contents of the RS485 byte.

    For example, if the byte (after the pass-byte) is "01001101", I need PORTB pins 0, 2, 3, and 7 to go high.

    My DIP switch has 5 switches.

    Can I connect the switch to PORTA 0-5, 2 LEDs to the remaining portA pins, 6 LEDs to PORTB, and use the remaining 2 portBs as the UART?

    Also, will the 16F88's internal 8MHz oscillator do the trick?

  3. AlexR

    Well-Known Member

    Jan 16, 2008
    The UART on the PIC16F88 receives data on port B pin 2 and transmits on port B pin 11. These pins are fixed and if you want to use the UART you have to arrange your port/pin allocation with this in mind.

    Another factor to keep in mind is that you can enable internal pull-up resistors on port B pins which makes them the logical choice for the switch connection. If you use port A for the switch you will need to provide your own pull-ups.

    The internal oscillator should be good enough for your application since asynchronous communications re-syncs after every 10 bits and therefore does not need a super accurate clock.
  4. Tekk

    Thread Starter Member

    Apr 18, 2009
    Ok, thanks. So basically I need to:

    1. put "12" in SPBRG for 9.6Kbaud at 4MHz, set bit BRGH
    2. Clear bit SYNC, set bit SPEN (serial port enable)
    3. Set bit CREN (receive enable)
    4. Receive
    5. Flag bit RCIF will be set when done receiving
    6. Read contents of RCSTA for the value received
    7. If value is 35 decimal (ascii for "#") set a bit in some GPR
    8. Repeat to listen for the address
    9. If LSBs of the next byte are the same as the DIP switch values set another bit in a GPR
    10. Repeat to listen for the LED byte
    11. Move that to PORTB
    12. Clear the GPR bits
    7. Repeat starting at step 4

    (info gathered from 16F88 datasheet)

  5. Tekk

    Thread Starter Member

    Apr 18, 2009
    Whoops, thought SPBRG should be 12. Closer examination of the datasheet reveals that I was wrong :rolleyes:.

    I wrote my program:

    Code ( (Unknown Language)):
    2. ;***************************************************************
    3. pound    equ    20h        ;var for Pound sign ASCII
    4. address equ    21h        ;var for PIC's address
    5. ;***************************************************************
    6.     org    0x0004        ;Using a bootloader
    7. INIT    CLRF    PORTA
    8.     CLRF    PORTB
    9.     BSF    STATUS,RP0    ;Select Bank 1
    10.     CLRF    ANSEL        ;All pins are Digital
    11.     BSF    OSCCON,6    ;Set oscilator to 4Mhz
    12.     BSF    OSCCON,5
    13.     MOVLW    H'07'
    14.     MOVWF    CMCON        ;Turn off comparators
    15.     MOVLW    B'01011011'    ;PortB 0,1,3,4, and 6 are inputs
    16.                 ;UART Rx PORTB 2
    17.                 ;UART Tx PORTB 5
    18.     MOVWF    TRISB
    19.     CLRF     TRISA        ;All PORTA is output
    20.     BCF    OPTION_REG,7    ;Enable PORTB internal pullups on inputs
    21.     MOVLW    D'25'        ;9.6Kbaud at 4MHz
    22.     MOVWF    SPBRG        ;Move to Baud Rate Generator
    23.     BCF    STATUS,RP0    ;Select Bank 0
    24.     BSF     RCSTA,7        ;Enable the serial port
    25.     BSF    RCSTA,4        ;Enable serial receive
    26.     BSF    TXSTA,5        ;Enable serial transmit
    27.     BSF    TXSTA,2        ;Enable high-speed mode
    28.     MOVLW    b'00100011'    ;Put the pound sign in a GPR
    29.     MOVWF    pound
    30.     CLRF    address        ;Clear the address var
    31.     BTFSC    PORTB,0        ;Is the first DIP on?
    32.     BSF    address,0    ;If so, put a 1 in bit 1 of address
    33.     BTFSC    PORTB,1        ;repeat
    34.     BSF    address,1
    35.     BTFSC    PORTB,3        ;skipping PORTB 2 and 5 because they are UART
    36.     BSF    address,2
    37.     BTFSC    PORTB,4
    38.     BSF    address,3
    39.     BTFSC    PORTB,6
    40.     BSF    address,4
    42. Start    BTFSS    PIR1,5        ;Check if a byte has been received
    43.     GOTO    Start        ;If not, loop
    44.     MOVLW    pound       ;Load pound sign ASCII into W
    45.     SUBWF    RCREG,0        ;Check to see if the byte received is ASCII 35 ("#")
    46.     BTFSS    STATUS,2    ;Was it?
    47.     GOTO    Start        ;If not, go back.
    49. Byte2    BTFSS    PIR1,5        ;If so, receive another byte (PIC address)
    50.     GOTO    Byte2        ;No byte? Go back receiving the address.
    51.     MOVLW    address        ;Move values of DIP Switch on PortB to W
    52.     SUBWF    RCREG,0        ;Check to see if the byte received is this PIC's address
    53.     BTFSS    STATUS,2    ;Was it?
    54.     GOTO    Start        ;If not, go back to the very beginning.
    56. Byte3    BTFSS    PIR1,5        ;If so, receive one more byte
    57.     GOTO     Byte3        ;No byte? Keep receiving.
    58.     BTFSC    RCREG,0        ;Should LED 0 be on?
    59.     BSF    PORTB,7        ;Then turn the 1st led on
    60.     BTFSC    RCREG,1        ;Repeat for other LEDs
    61.     BSF    PORTA,0        
    62.     BTFSC    RCREG,2
    63.     BSF    PORTA,1
    64.     BTFSC    RCREG,3
    65.     BSF    PORTA,2
    66.     BTFSC    RCREG,4
    67.     BSF    PORTA,3
    68.     BTFSC    RCREG,5
    69.     BSF    PORTA,5        ;Skipping PORTA bit 4 because it's open-collector
    70.     BTFSC    RCREG,6
    71.     BSF    PORTA,6
    72.     BTFSC    RCREG,7
    73.     BSF    PORTA,7
    74.     GOTO    Start
    76.     END
    Thanks to everyone for the help and feel free to look at my program to see if I missed anything.
    Last edited: Apr 19, 2009