Usinge serial lines from user space(Linux-rs485)

转载:https://www.acmesystems.it/rs485

This is a basic example on how to use a serial port in Pyhon using the pySerial module:

import serial
 
ser = serial.Serial(
    port='/dev/ttyS1', 
    baudrate=9600, 
    timeout=1,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)  
 
ser.write("A")      # Send a "A" char to the serial port
s = ser.read(1)     # Wait for a char
print s
ser.close()
Read any bytes received on serial line and print out on stdout in hex format:

import sys
import serial
 
ser = serial.Serial(
    port='/dev/ttyUSB1', 
    baudrate=9600, 
    timeout=1,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)  

linecounter=0
bytecounter=0
bytesperline = 8
while True:     
    bytesToRead = ser.inWaiting()
    
    if bytesToRead>0:
        value=ser.read(1)
        if (bytecounter % bytesperline) == 0:
            print "\n[%04X] - " % bytecounter ,
            sys.stdout.flush()
            linecounter=linecounter+1
             
        print "%02X " % ord(value) ,
        sys.stdout.flush()
        bytecounter=bytecounter+1
        if bytecounter==0:
            print
            bytecounter=0

This is a basic example on how to use a serial port in C.

Refer to these links to understand how it works.

#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"
 
int main(void) {
    char txBuffer[10];
    char rxBuffer[10];
    int fd;
    struct termios tty_attributes;
 
    if ((fd = open("/dev/ttyS1",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);
 
        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;
}

Enable the DMA on serial lines

    /* /dev/ttyS1 */
    usart0: serial@f801c000 {
        pinctrl-0 = <&pinctrl_usart0
                 &pinctrl_usart0_rts
                 &pinctrl_usart0_cts
                 >;
        status = "okay";

        atmel,use-dma-rx;
        atmel,use-dma-tx;
        
        dmas = <&dma0 1 0x3>,<&dma0 1 0x204>;
        
        /*dmas = <&dma0 1 AT91_DMA_CFG_PER_ID(3)>,
               <&dma0 1 AT91_DMA_CFG_FIFOCFG_ASAP | AT91_DMA_CFG_PER_ID(4)>;*/
               
        dma-names = "tx", "rx";                     
    };

Related links

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

RS485 without DTS on Kernel version < 3.4

If you are using an old Kernel Linux without the device tree you have to setup the rs485 hardware mode as illustrated below:

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;
}

RS485 with DTS on Kernel version >= 3.4

If you are using a recent Linux Kernel with device tree enabled you have to specify inside the device tree source the RS485. After that you can open the serial port as a normal RS232 port.

This is an example for the /dev/ttyS2 on Aria G25 or Arietta G25 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.

Python example

This example sends a char on the RS485 bus using a DAISY-10 board wired on the /dev/ttyS2 serial port. If you are using a Terra board plug the DAISY-10 on D10 connector (..see the Terra pinout).

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()
 
ser.write("0123456789") # Send some char on the RS485 bus
s = ser.read(1)         # Wait for a char
print s
ser.close()

Related links





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值