RS485 lines

EIA-485, also known as TIA/EIA-485 or RS-485, is a standard defining the electrical characteristics of drivers and receivers for use in balanced digital multipoint systems. This standard is widely used for communications in industrial automation because it can be used effectively over long distances and in electrically noisy environments

Starting from its version 2.6.38 the Linux Kernel provides the serial_rs485 structure to handle RS485 communications on the hardware that can support it like the Atmel AT91SAM CPU. This data structure is used to set and configure RS485 parameters in the platform data and in ioctls.

The ioctl TIOCSRS485 (typically associated with number 0x542F) is used to enable/disable RS485 mode from user-space.

Python example

import serial,fcntl, struct
 
ser = serial.Serial(
    port='/dev/ttyS2', 
    baudrate=9600, 
    timeout=1,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)  
 
fd=ser.fileno()
serial_rs485 = struct.pack('hhhhhhhh', 1, 0, 0, 0, 0, 0, 0, 0)
fcntl.ioctl(fd,0x542F,serial_rs485)
 
 
ser.write("A")      # Send a "A" char to the serial port
s = ser.read(1)         # Wait for a char
print s
ser.close()

C example

#include "stdio.h"     
#include "string.h"    
#include "unistd.h"    
#include "fcntl.h"     
#include "errno.h"     
#include "sys/types.h"
#include "sys/stat.h"
#include "stdlib.h"
#include "stdarg.h"
#include "termios.h"
#include "linux/serial.h"  
 
#define TIOCSRS485 0x542F
 
int main(void) {
    char txBuffer[10];
    char rxBuffer[10];
    int fd;
    struct termios tty_attributes;
    struct serial_rs485 rs485conf;
 
    if ((fd = open("/dev/ttyS2",O_RDWR|O_NOCTTY|O_NONBLOCK))<0) {
        fprintf (stderr,"Open error on %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    } else {
        tcgetattr(fd,&tty_attributes);
 
        // c_cflag
        // Enable receiver
        tty_attributes.c_cflag |= CREAD;        
 
        // 8 data bit
        tty_attributes.c_cflag |= CS8;          
 
        // c_iflag
        // Ignore framing errors and parity errors. 
        tty_attributes.c_iflag |= IGNPAR;       
 
        // c_lflag
        // DISABLE canonical mode.
        // Disables the special characters EOF, EOL, EOL2, 
        // ERASE, KILL, LNEXT, REPRINT, STATUS, and WERASE, and buffers 
        // by lines.
 
        // DISABLE this: Echo input characters.
        tty_attributes.c_lflag &= ~(ICANON);     
 
        tty_attributes.c_lflag &= ~(ECHO);      
 
        // DISABLE this: If ICANON is also set, the ERASE character 
        // erases the preceding input   
        // character, and WERASE erases the preceding word.
        tty_attributes.c_lflag &= ~(ECHOE);     
 
        // DISABLE this: When any of the characters INTR, QUIT, SUSP, 
        // or DSUSP are received, generate the corresponding signal.    
        tty_attributes.c_lflag &= ~(ISIG);      
 
        // Minimum number of characters for non-canonical read.
        tty_attributes.c_cc[VMIN]=1;            
 
        // Timeout in deciseconds for non-canonical read.
        tty_attributes.c_cc[VTIME]=0;           
 
        // Set the baud rate
        cfsetospeed(&tty_attributes,B9600);     
        cfsetispeed(&tty_attributes,B9600);
 
        tcsetattr(fd, TCSANOW, &tty_attributes);
 
        // Set RS485 mode: 
        rs485conf.flags |= SER_RS485_ENABLED;
        if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
            printf("ioctl error\n");
        }
 
        txBuffer[0]='A';
        write(fd,txBuffer,1);
 
        // Read a char
        if (read(fd,&rxBuffer,1)==1) {
            printf("%c",rxBuffer[0]);
            printf("\n");
        }   
    }   
 
    close(fd);  
    return EXIT_SUCCESS;
}

Device tree binding on Linux > 3.11

If you are using Linux 3.11 or higher you have to enable the RS485 on device tree source file as explained here:

This is an example for the /dev/ttyS2 on CORE9G25 module:

usart3: serial@f8028000 {
    compatible = "atmel,at91sam9260-usart";
    reg = <0xf8028000 0x200>;
    interrupts = <8 4 5>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_usart3
             &pinctrl_usart3_rts 
             &pinctrl_usart3_cts
            >;
     linux,rs485-enabled-at-boot-time;
     rs485-rts-delay = <0 20>;
    status = "okay";
};

The rs485-rts-delay parms are in 0.1 mS instead on mS as written on the Kernel doc.

To know how to create a device tree file read this tutorial: Compiling the Linux Kernel 3.11.6 for the CORE9G25.

Related links

 

Documentation Terms of Use
The Acme Systems srl provides this Debian system development and user manual.
The origin of these doc came from the website: http://www.acmesystems.it
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Creative Commons License


Market Mail : market@armdevs.com
Support Mail: support@armdevs.com Sales Phone: +86-755-29638421


CoreWind Online Chat>
Work time: 09:00-18:00
Copyright @ 2014 to 2020 - CoreWind Tech.