chipKIT® Development Platform

Inspired by Arduino™

RS485 Addressing for Serial

Created Wed, 28 Jan 2015 17:35:17 +0000 by thejosheb


thejosheb

Wed, 28 Jan 2015 17:35:17 +0000

I made a few changes to the HardwareSerial library to initiate the uart module for addressable RS485 communications. The PIC32 Family Reference Manual, specifically section 21.8, has more information, but when the another device sends a byte with the 9th bit set, the uart module will check the sent byte against the programmed address. If the address matches, the uart module will automatically disable address detection and every byte sent after that will initiate an interrupt and start filling the library's buffer like the normal. Interrupts will continue this way until you, the programmer, re-enable address detection by calling enableAddressDetection() when the end of the message is sent determined by the protocol you are using. One side note, the sent address byte is discarded and never sent to the library's buffer.

void HardwareSerial::begin(unsigned long baudRate, uint8_t address) {
    //	p32_regset *	ipc;	//interrupt priority control register set
    //	int				irq_shift;

    /* Initialize the receive buffer.
    */
    purge();

#if defined(__PIC32MX1XX__) || defined(__PIC32MX2XX__)
    /* Map the UART TX to the appropriate pin.
    */
    mapPps(pinTx, ppsTx);

    /* Map the UART RX to the appropriate pin.
    */
    mapPps(pinRx, ppsRx);
#endif

    setIntVector(vec, isr);

    /* Set the interrupt privilege level and sub-privilege level
    */
    setIntPriority(vec, ipl, spl);
    
    /* Clear the interrupt flags, and set the interrupt enables for the
    ** interrupts used by this UART.
    */
    ifs->clr = bit_rx + bit_tx + bit_err;	//clear all interrupt flags

    iec->clr = bit_rx + bit_tx + bit_err;	//disable all interrupts
    iec->set = bit_rx;						//enable rx interrupts

    /* Initialize the UART itself.
    **	http://www.chipkit.org/forum/viewtopic.php?f=7&t=213&p=948#p948
    ** Use high baud rate divisor for bauds over LOW_HIGH_BAUD_SPLIT
    */
    uart->uxMode.reg = 0;
    uart->uxSta.reg = 0;
    if (baudRate < LOW_HIGH_BAUD_SPLIT) {
        // calculate actual BAUD generate value.
        uart->uxBrg.reg = ((__PIC32_pbClk / 16 / baudRate) - 1);  
        // set to 9 data bits, no parity
        uart->uxMode.set = 0b11 << _UARTMODE_PDSEL;                             
    } else {
        // calculate actual BAUD generate value.
        uart->uxBrg.reg = ((__PIC32_pbClk / 4 / baudRate) - 1);
        // set to 9 data bits, no parity
        uart->uxMode.set =  (1 << _UARTMODE_BRGH) + (0b11 << _UARTMODE_PDSEL); 
    }
    // set address of RS485 slave, enable transmitter and receiver and auto address detection
    uart->uxSta.set = (1 << _UARTSTA_ADM_EN) + (address << _UARTSTA_ADDR) + (1 << _UARTSTA_UTXEN) + (1 << _UARTSTA_URXEN);  
    enableAddressDetection(); // enable auto address detection
    uart->uxMode.set = 1 << _UARTMODE_ON; // enable UART module
}

void HardwareSerial::enableAddressDetection(void) {
    uart->uxSta.set = 1 << _UARTSTA_ADDEN;
}

void HardwareSerial::disableAddressDetection(void) {
    uart->uxSta.clr = 1 << _UARTSTA_ADDEN;
}

majenko

Wed, 28 Jan 2015 17:59:08 +0000

Nice one.

You know, you should really fork the Github repository and submit that as a pull request.


thejosheb

Wed, 28 Jan 2015 21:36:08 +0000

I have submitted a pull request


PeteD

Sun, 22 Feb 2015 17:32:45 +0000

This is great, but I have a client the pic usart using 9bit tx, and instead of address detection they use the 9th bit to indicate a command vs. data. Can I toggle that bit somehow? How do you set this up to use pin17 on Fubarino mini?

Is it possible to use the regular Serial libraries to set 9 bit data and toggle the TX9


thejosheb

Mon, 23 Feb 2015 14:38:28 +0000

First, I'm not really sure about pins on the Fubarino mini. After a quick search in the code it looks like pin17 is used for TX for Serial0. As for 9bit communication, transmit and receive, the short answer in no, not with the Serial library as is. You'll have to do a bit of rewriting of the Serial library, as most of the variables in the class are only 8bit wide. The family reference manual for the UART module has a section dedicated to 9bit communication. Section 21.8.1.2 talks about 9bit transmission.