Difference between revisions of "How to use RS485"
From IGEP - ISEE Wiki
Line 10: | Line 10: | ||
= Add RS-485 support to Linux = | = Add RS-485 support to Linux = | ||
+ | |||
+ | === Using kernel 2.6.35.13 === | ||
+ | |||
+ | In this kernel is not necessary add RS-485 support | ||
=== Using kernel 2.6.33 series === | === Using kernel 2.6.33 series === |
Revision as of 11:06, 6 October 2011
Contents
[hide]Overview of How-To
This How-To is meant to be a starting point for people to learn to use the RS-485 port on IGEP0020 board.
Below this How-To is a short .c file which describe how to setup and write data on the RS-485 port.
Feedback and Contributing
At any point, if you see a mistake you can contribute to this How-To.
Add RS-485 support to Linux
Using kernel 2.6.35.13
In this kernel is not necessary add RS-485 support
Using kernel 2.6.33 series
Follow http://www.igep.es/index.php?option=com_kunena&Itemid=97&func=view&catid=13&id=1195&limit=6
Using kernel 2.6.28 series
Tested on a 2.6.28.10-3 version kernel.
To use correctly the RS-485 interface chip we need to configure the serial port driver in the kernel to manage the RTS signal (Request To Send) to enable the TX section (DE pin) only when data are transmitted on TXD line (Transmit Data). This is a software only solution, requiring no special hardware, but timing control for delays is only accurate to the next nearest jiffy.
First of all, download the latest stable kernel version
$ wget http://downloads.igep.es/sources/kernel/linux-omap-2.6.28.10-3.tar.gz $ tar xzf linux-omap-2.6.28.10-3.tar.gz $ cd linux-omap-2.6.28.10-3 $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- igep0020_defconfig
Next, enable the RS-485 support.
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig
Configure the kernel to enable RS-485 support.
Device drivers ---> Character devices ---> Serial drivers ---> *** serial port extensions *** [*] Allow hand shake line half duplex direction signaling
Finally build kernel image with RS-485 support
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
Test RS-485 communication with two IGEP0020 boards
Connect two IGEP0020 boards using J940 connector like this:
J940 J940 --- --- | 1 |---------- GND ----------| 1 | | 2 |-X X-| 2 | | 3 |-X X-| 3 | | 4 |---------- A ----------| 4 | | 5 |---------- B ----------| 5 | --- ---
Setup a NFS-TFTP environment (poky-image-sato) for each board using kernel image with RS-485 support, and power up
Build the example for your target boards,
$ cd linux-omap-2.6.28.10-3 $ arm-none-linux-gnueabi-gcc 485-example.c -o 485-example -Iinclude -Iarch/arm/include
and copy to target rootfs.
Now, open a ssh console to the first board and execute the microcom command:
root@igep0020:~# microcom /dev/ttyS0 connected to '/dev/ttyS0' (9600 bps), exit with ctrl-X...
On second board, open a ssh and execute the 485 example:
root@igep0020:~# ./485-example
If all is ok, should appear "ABC" in microcom console.
root@igep0020:~# microcom /dev/ttyS0 connected to '/dev/ttyS0' (9600 bps), exit with ctrl-X... ABC
Appendix A: 485-example.c : Basic example of RS-485 half duplex transmission
/* 485-example.c : Basic example of RS485 half duplex transmission */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <termios.h> #include <sys/ioctl.h> #include <asm/ioctls.h> #include <linux/rs485.h> int main(void) { char dev[] = "/dev/ttyS0"; char tosend[] = {'A', 'B', 'C'}; struct serial_rs485_settings ctrl485; int status; int fd; struct termios ti; speed_t speed; /* Open the port */ fd = open(dev, O_RDWR); if (fd < 0) { printf("%s: Unable to open.\n", dev); return -1; } /* Set the port in 485 mode */ ctrl485.flags = SER_RS485_MODE | SER_RS485_MODE_RTS | SER_RS485_RTS_TX_LOW; ctrl485.delay_before_send = 0; ctrl485.delay_after_send = 0; status = ioctl(fd, TIOCSRS485, &ctrl485); if (status) { printf("%s: Unable to configure port in 485 mode, status (%i)\n", dev, status); return -1; } /* Set the port speed */ speed = B9600; tcgetattr(fd, &ti); cfsetospeed(&ti, speed); cfsetispeed(&ti, speed); tcsetattr(fd, TCSANOW, &ti); /* Send content to RS485 */ if (write(fd, tosend, sizeof(tosend)) != sizeof(tosend)) { printf("%s: write() failed\n", dev); } return 0; }
References
- Discussions on RS-485 auto direction control seem to be split over a number of threads. Here are some threads:
- http://marc.info/?t=121805745200001&r=1&w=2
- http://marc.info/?t=121690034200007&r=1&w=2
- http://marc.info/?t=122821576400003&r=1&w=2
- http://marc.info/?t=122822457300004&r=1&w=2
- http://marc.info/?t=122954923400001&r=1&w=2
- http://marc.info/?t=122964426200001&r=1&w=2
- http://marc.info/?t=121566595900001&r=1&w=2
- http://marc.info/?t=121805198200004&r=1&w=2
ISEE References
Read the Official IGEP0020 Hardware Reference Manual (chapter "5.3 CONNECTOR J940: POWER + RS-485" )