自动更改 RS-485 通信的 RTS [英] automatically changing RTS for RS-485 communication

查看:16
本文介绍了自动更改 RS-485 通信的 RTS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的程序中设置半双工通信.我的 RS485 收发器使用 RTS 标志 (TIOCM_RTS) 在发送和接收之间来回切换.要发送/接收数据,我需要手动更改 RTS 标志:

  1. 将 RTS 设置为高.

  2. 发送数据.

  3. 将 RTS 设置为低.

    int setRTS(int level) {整数状态;ioctl(ser_port, TIOCMGET, &状态);如果(级别){状态|= TIOCM_RTS;} 别的 {状态 &= ~TIOCM_RTS;}ioctl(ser_port, TIOCMSET, &status);返回 1;}

我的问题是:linux内核不应该能够自动切换RTS吗?以及如何确保在调用 setRTS(0) 之前发送了数据?

解决方案

linux内核不应该可以自动切换RTS吗?

是的,从 Linux 3.0 开始就有这样的内核框架.
include/uapi/asm-generic/ioctls.h中有两个ioctl:

#define TIOCGRS485 0x542E#define TIOCSRS485 0x542F

在 RS-485 模式下检索和配置 tty 串行端口驱动程序.
这些 ioctl 使用 struct serial_rs485:

<代码>/** 串行接口,用于控制芯片上的 RS485 设置,具有合适的* 支持.如果您的支持,请使用 TIOCSRS485 设置并获取 TIOCGRS485* 平台.set 函数返回新状态,包含任何不支持的位* 适当还原.*/结构序列_rs485 {__u32 标志;/* RS485 功能标志 */#define SER_RS485_ENABLED (1 <<0)/* 如果启用 */#define SER_RS485_RTS_ON_SEND (1 <<1)/* 逻辑级别RTS 引脚时发送 */#define SER_RS485_RTS_AFTER_SEND (1 <<2)/* 逻辑级别发送后的 RTS pin*/#define SER_RS485_RX_DURING_TX (1 <<4)__u32 delay_rts_before_send;/* 发送前延迟(毫秒) */__u32 delay_rts_after_send;/* 发送后延迟(毫秒) */__u32 填充[5];/* 内存很便宜,新结构是皇家 PITA .. */};

我已在 Atmel 和 Etrax SoC 上使用此 RS-485 功能,但在 Linux UART/USART 驱动程序中这些 ioctl 的实现非常少.
如果您的驱动程序没有它,那么请考虑自己实现它.您可以使用 drivers/tty/serial/atmel_serial.c 中的实现作为指南.另请阅读 RS485 的 Linux 内核文档.p>

I'm trying to setup half duplex communication in my program. I have my RS485 transceiver using the RTS flag (TIOCM_RTS) to toggle back and forth between transmit and receive. And to send/receive data I need to change RTS flag manually:

  1. Set RTS to High.

  2. Send data.

  3. Set RTS to low.

    int setRTS(int level) {
        int status;
        ioctl(ser_port, TIOCMGET, &status);
        if(level) {
            status |= TIOCM_RTS;
        } else {
            status &= ~TIOCM_RTS;
        }
        ioctl(ser_port, TIOCMSET, &status);
        return 1;
    }
    

My question is: shouldn't the linux kernel be able to switch RTS automatically? And how to ensure that data was sent before calling setRTS(0)?

解决方案

shouldn't the linux kernel be able to switch RTS automatically?

Yes, there is kernel framework for this starting in Linux 3.0.
There are two ioctls in include/uapi/asm-generic/ioctls.h:

#define TIOCGRS485      0x542E
#define TIOCSRS485      0x542F

to retrieve and configure a tty serial port driver in RS-485 mode.
These ioctls use the struct serial_rs485:

 /*
  * Serial interface for controlling RS485 settings on chips with suitable
  * support. Set with TIOCSRS485 and get with TIOCGRS485 if supported by your
  * platform. The set function returns the new state, with any unsupported bits
  * reverted appropriately.
  */

 struct serial_rs485 {
         __u32   flags;                  /* RS485 feature flags */
 #define SER_RS485_ENABLED               (1 << 0)        /* If enabled */
 #define SER_RS485_RTS_ON_SEND           (1 << 1)        /* Logical level for
                                                            RTS pin when
                                                            sending */
 #define SER_RS485_RTS_AFTER_SEND        (1 << 2)        /* Logical level for
                                                            RTS pin after sent*/
 #define SER_RS485_RX_DURING_TX          (1 << 4)
         __u32   delay_rts_before_send;  /* Delay before send (milliseconds) */
         __u32   delay_rts_after_send;   /* Delay after send (milliseconds) */
         __u32   padding[5];             /* Memory is cheap, new structs
                                            are a royal PITA .. */
 };

I've used this RS-485 capabilty on Atmel and Etrax SoCs, but otherwise implementation of these ioctls in Linux UART/USART drivers is very sparse.
If your driver doesn't have it, then consider implementing it yourself. You could use the implementation in drivers/tty/serial/atmel_serial.c as a guide. Also read the Linux kernel document for RS485.

这篇关于自动更改 RS-485 通信的 RTS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆