首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当RS485在设备树覆盖中启用时,SC16IS752上的硬件RTS不能工作

当RS485在设备树覆盖中启用时,SC16IS752上的硬件RTS不能工作
EN

Unix & Linux用户
提问于 2019-09-12 20:44:12
回答 1查看 1.6K关注 0票数 2

我试图通过使用设备树覆盖(在引导时不运行C应用程序)使SC16IS752 (SPI到UART转换器)在RS485模式下工作。

我从github的官方来源获取了SC16IS752的原始覆盖源:

sc16is752-spi1-overlay.dts

不添加linux,rs485-enabled-at-boot-time;行,它的工作方式如下:(RTS总是很高)

我像这样更改了fragment@1部件并添加了RS485 (我还更改了时钟freq,因为我在硬件中使用的是1.843200MHz晶体,而不是14.xxMHz):

代码语言:javascript
运行
复制
fragment@1 {
    target = <&spi1>;
    frag1: __overlay__ {
        #address-cells = <1>;
        #size-cells = <0>;
        pinctrl-names = "default";
        pinctrl-0 = <&spi1_pins &spi1_cs_pins>;
        cs-gpios = <&gpio 18 1>;
        status = "okay";

        /* RS485 SUPPORT */
        linux,rs485-enabled-at-boot-time;
        rs485-rts-delay = <0 0>;
        /* RS485 SUPPORT END */

        sc16is752: sc16is752@0 {
            compatible = "nxp,sc16is752";
            reg = <0>; /* CE0 */
            clocks = <&sc16is752_clk>;
            interrupt-parent = <&gpio>;
            interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
            gpio-controller;
            gpio-cells = <2>;
            spi-max-frequency = <4000000>;

            /* I also tried to put it here */
            /* but RTS is always HIGH */
            /* RS485 SUPPORT */
            /* linux,rs485-enabled-at-boot-time; */
            /* rs485-rts-delay = <0 0>; */
            /* RS485 SUPPORT END */

            sc16is752_clk: sc16is752_clk {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <1843200>;
            };
        };
    };
};

我编译了dts文件,并将其放到/boot/overlays中,并在/boot/config.txt中添加了正确的行来使用覆盖。

RTS行现在总是低的(没有标志,它是高的-见上图):

所以这个标志已经被内核/驱动程序读取了,但是RTS在我发送数据时什么也不做。它应该是这样的:

最后一次使用RS485模式的屏幕截图是在我在C程序中转换RS485模式之后拍摄的,如下所示:

代码语言:javascript
运行
复制
#include <fcntl.h>
#include <unistd.h>
#include <linux/serial.h>

/* Include definition for RS485 ioctls: TIOCGRS485 and TIOCSRS485 */
#include <sys/ioctl.h>

int main(int argc, char *artv[]){

        /* Open your specific device (e.g., /dev/mydevice): */
        int fd = open ("/dev/ttySC0", O_RDWR);
        if (fd < 0) {
                /* Error handling. See errno. */
                return -1;
        }

        struct serial_rs485 rs485conf;

        /* Enable RS485 mode: */
        rs485conf.flags |= SER_RS485_ENABLED;

        /* Set logical level for RTS pin equal to 1 when sending: */
        rs485conf.flags |= SER_RS485_RTS_ON_SEND;
        /* Set logical level for RTS pin equal to 0 after sending: */
        rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);

        rs485conf.delay_rts_before_send = 0;
        rs485conf.delay_rts_after_send = 0; // zero! nie obsługiwane przez SC16IS752

        if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
                /* Error handling. See errno. */
                return -2;
        }

        /* Use read() and write() syscalls here... */

        /* Close the device when finished: */
        if (close (fd) < 0) {
                /* Error handling. See errno. */
                return -3;
        }

        return 0;
}

那么,问题是如何在没有C程序的情况下做到这一点呢?

为什么在设备树中设置rs485模式是不够的?

我怀疑驱动程序没有默认配置,并且在SER_RS485_RTS_ON_SEND和SER_RS485_RTS_AFTER_SEND标志中都有零。如果这是真的-(额外的问题)我应该报告这个司机在这种情况下的问题吗?

有用的资源:

编辑/添加后:

我还注意到,当我的覆盖在引导时被应用并运行这段代码(它应该从端口读取标志,我不确定它是否正确)。

代码语言:javascript
运行
复制
    /* Reading rs485conf struct from port */
    if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
            /* Error handling. See errno. */
            return -2;
    }

    printf("Before: ");
    binprintf(rs485conf.flags); // function that prints int as binary
    printf("\n");

所有的旗帜都是空的。所以..。启动后覆盖更改了RTS状态,但是端口上的标志是零吗?我不明白。

EN

回答 1

Unix & Linux用户

发布于 2020-11-02 13:03:32

如果有人发现了这个问题,就像我试图让SC16IS752在I2C上使用RPi时一样,答案是:

  • sc16is7xx.c驱动程序没有任何调用uart_get_rs485_mode()的代码,这些代码在serial_core.c中描述,并出现在其他几个串行驱动程序中;
  • 设备树属性rs485-rts-active-low似乎只添加到RPi 5.3和更高版本的内核中(参见此提交)。

为了解决第一个问题,我对sc16is7xx.c驱动程序做了几处小更改,请参阅此提交uart_get_rs485_mode()函数从设备树中获取相关属性,并写入一个struct serial_rs485,与TIOCSRS485 ioctl使用的相同。这些更改还没有经过回归测试,但目前它在我的SC16IS752接口上对我来说是可靠的。

此提交基于5.4内核,因此支持rs485-rts-active-low属性,因此可以很好地与MAX3072行驱动程序一起工作。

下面是我的覆盖文件的一部分:

代码语言:javascript
运行
复制
fragment@1 {
    target = <&i2c_arm>;
    __overlay__ {
        #address-cells = <1>;
        #size-cells = <0>;
        status = "okay";

        sc16is752: sc16is752@48 {
            compatible = "nxp,sc16is752";
            reg = <0x48>; /* i2c address */
            clocks = <&sc16is752_clk>;
            interrupt-parent = <&gpio>;
            interrupts = <18 2>; /* IRQ_TYPE_EDGE_FALLING */
            gpio-controller;
            #gpio-cells = <2>;
            i2c-max-frequency = <400000>;
            linux,rs485-enabled-at-boot-time;
            rs485-rts-active-low;
        };
    };
};

下面是一个显示它工作的范围图像:

参考:D8=SCLD9=SDAD10=_IRQD11=TXDD12=_RTSD13=RXDAnalog1=one RS485 lineAnalog2=RXD (与D13相同)。命令响应来自远程ModBus设备。请注意,在传输期间,_RTS很高(3.3V),因为存在双重否定。

票数 0
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/541473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档