PIC 16F88 and RS-485

Thread Starter

Tekk

Joined Apr 18, 2009
16
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,
Matt
 

Thread Starter

Tekk

Joined Apr 18, 2009
16
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?

Thanks!
 

AlexR

Joined Jan 16, 2008
732
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.
 

Thread Starter

Tekk

Joined Apr 18, 2009
16
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)

Right?
 

Thread Starter

Tekk

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

I wrote my program:

Rich (BB code):
;***************************************************************
pound    equ    20h        ;var for Pound sign ASCII
address equ    21h        ;var for PIC's address
;***************************************************************
    org    0x0004        ;Using a bootloader
INIT    CLRF    PORTA
    CLRF    PORTB
    BSF    STATUS,RP0    ;Select Bank 1
    CLRF    ANSEL        ;All pins are Digital
    BSF    OSCCON,6    ;Set oscilator to 4Mhz
    BSF    OSCCON,5
    MOVLW    H'07'
    MOVWF    CMCON        ;Turn off comparators
    MOVLW    B'01011011'    ;PortB 0,1,3,4, and 6 are inputs
                ;UART Rx PORTB 2
                ;UART Tx PORTB 5
    MOVWF    TRISB
    CLRF     TRISA        ;All PORTA is output
    BCF    OPTION_REG,7    ;Enable PORTB internal pullups on inputs
    MOVLW    D'25'        ;9.6Kbaud at 4MHz
    MOVWF    SPBRG        ;Move to Baud Rate Generator
    BCF    STATUS,RP0    ;Select Bank 0
    BSF     RCSTA,7        ;Enable the serial port
    BSF    RCSTA,4        ;Enable serial receive
    BSF    TXSTA,5        ;Enable serial transmit
    BSF    TXSTA,2        ;Enable high-speed mode
    MOVLW    b'00100011'    ;Put the pound sign in a GPR
    MOVWF    pound
    CLRF    address        ;Clear the address var
    BTFSC    PORTB,0        ;Is the first DIP on?
    BSF    address,0    ;If so, put a 1 in bit 1 of address
    BTFSC    PORTB,1        ;repeat
    BSF    address,1
    BTFSC    PORTB,3        ;skipping PORTB 2 and 5 because they are UART
    BSF    address,2
    BTFSC    PORTB,4
    BSF    address,3
    BTFSC    PORTB,6
    BSF    address,4

Start    BTFSS    PIR1,5        ;Check if a byte has been received
    GOTO    Start        ;If not, loop
    MOVLW    pound       ;Load pound sign ASCII into W
    SUBWF    RCREG,0        ;Check to see if the byte received is ASCII 35 ("#")
    BTFSS    STATUS,2    ;Was it?
    GOTO    Start        ;If not, go back.

Byte2    BTFSS    PIR1,5        ;If so, receive another byte (PIC address)
    GOTO    Byte2        ;No byte? Go back receiving the address.
    MOVLW    address        ;Move values of DIP Switch on PortB to W
    SUBWF    RCREG,0        ;Check to see if the byte received is this PIC's address
    BTFSS    STATUS,2    ;Was it?
    GOTO    Start        ;If not, go back to the very beginning.

Byte3    BTFSS    PIR1,5        ;If so, receive one more byte
    GOTO     Byte3        ;No byte? Keep receiving.
    BTFSC    RCREG,0        ;Should LED 0 be on?
    BSF    PORTB,7        ;Then turn the 1st led on
    BTFSC    RCREG,1        ;Repeat for other LEDs
    BSF    PORTA,0        
    BTFSC    RCREG,2
    BSF    PORTA,1
    BTFSC    RCREG,3
    BSF    PORTA,2
    BTFSC    RCREG,4
    BSF    PORTA,3
    BTFSC    RCREG,5
    BSF    PORTA,5        ;Skipping PORTA bit 4 because it's open-collector
    BTFSC    RCREG,6
    BSF    PORTA,6
    BTFSC    RCREG,7
    BSF    PORTA,7
    GOTO    Start

    END
Thanks to everyone for the help and feel free to look at my program to see if I missed anything.
 
Last edited:
Top