转载: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
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()