6

我正在尝试使用运行 Angstrom(3.8 内核)的 Beaglebone Black 与位于 9600-N-8-1 的半双工 RS-485 网络上的设备进行通信。

我正在尝试使用与此类似的 RS-485 分线板:https ://www.sparkfun.com/products/10124,除了芯片是 MAX3485 http://www.maximintegrated.com/datasheet/index .mvp/id/1079。我买了预装了引脚和端子排的电路板。我的一个朋友用示波器对其进行了测试,并声称 RS-485 板确实可以工作。该板有五个连接到 BBB 的引脚。3-5V(电源)、RX-I、TX-O、RTS 和 GND。

我已禁用 BBB 上的 HDMI 支持,以便UART4_RTSnUART4_CTSn引脚可用。

    mkdir /mnt/boot
    mount /dev/mmcblk0p1 /mnt/boot
    nano /mnt/boot/uEnv.txt
    #change contents of uEnv.txt to the following:
    optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN 

然后我找到了一个覆盖来启用带有 RTS/CTS 控制的 UART-4:

            /*
     * Modified version of /lib/firmware/BB-UART4-00A0.dtbo to add RTS so we can reset Arduinos
     */
    /dts-v1/;
    /plugin/;

    / {
      compatible = "ti,beaglebone", "ti,beaglebone-black";
      part-number = "BB-UART4-RTS";
      version = "00A0";
      exclusive-use = "P9.13", "P9.11", "P9.15", "P8.33", "P8.35", "uart4";

      fragment@0 {
        target = <0xdeadbeef>;

        __overlay__ {


          pinmux_bb_uart4_pins {
            pinctrl-single,pins = <
              0x070 0x26   /* P9_11 = UART4_RXD = GPIO0_30,    MODE6 */
              0x074 0x06   /* P9_13 = UART4_TXD = GPIO0_31,    MODE6 */
              /* need to enable both RTS and CTS, if we only turn on RTS then driver gets confused */
              0x0D0 0x26   /* P8_35 = UART4_CTSN = lcd_data12, MODE6 */
              0x0D4 0x06   /* P8_33 = UART4_RTSN = lcd_data13, MODE6 */
              /* 0x040 0x0F   /* P9_15 = GPIO1_16 = GPIO48,       MODE7  failed attempt to put DTR on gpio */
            >;
            linux,phandle = <0x1>;
            phandle = <0x1>;
          };
        };
      };

      fragment@1 {
        target = <0xdeadbeef>;

        __overlay__ {
          status = "okay";
          pinctrl-names = "default";
          pinctrl-0 = <0x1>;
        };
      };

      __symbols__ {
        bb_uart4_pins = "/fragment@0/__overlay__/pinmux_bb_uart4_pins";
      };

      __fixups__ {
        am33xx_pinmux = "/fragment@0:target:0";
        uart5 = "/fragment@1:target:0"; /* Not a mistake: UART4 is named uart5 */
      };

      __local_fixups__ {
        fixup = "/fragment@1/__overlay__:pinctrl-0:0";
      };
    };

编译并启用覆盖:

    cd /lib/firmware
    dtc -O dtb -o BB-UART4-RTS-00A0.dtbo -b 0 -@ BB-UART4-RTS-00A0.dts 
    echo BB-UART4-RTS:00A0  > /sys/devices/bone_capemgr.*/slots

像这样将485板连接到BB

    3-5V to P9_05 (VDD_5V)
    RX-I to P9_13 (UART4_TXD) 
    TX-O to P9_11 (UART4_RXD)
    RTS  to P8_33 (UART4_RTSn)
    GND  to P9_01 (DGND)

在python中,我试图像这样使用串口:

    import serial
    ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
    ser.write(list_of_byte_dat)

我知道该程序有效,因为当我使用 USB 到 RS-485 转换器/dev/ttyUSB0并设置rtscts=False通信在两个方向上都很好。但我无法使用 RS-485 板使通信正常工作。

RS-485 板有两个问题,都处理 RTS。

  1. 板上的 RTS 与我期望的方式相反。当我在 rs485 板的 RTS 引脚上施加电压时,板上的 RTS LED 熄灭,板不会传输。当我从 RTS 引脚移除电压时,RTS LED 会亮起,并且电路板将进行传输。如何反转 BBB 上 UART_RTSn 引脚的极性?

    Temporary solution: I've made a small bone script program that uses UART4_RTSn pin as input. It turns on a different GPIO when the UART4_RTSn pin is off and turns off that same GPIO pin when the UART4_RTSn pin is on. Then hooked up the RTS pin on the rs485 board to the GPIO pin instead of the UART4_RTSn pin.

    这似乎是一个糟糕的解决方案,但它确实使 RS485 板上的 RTS 在/dev/ttyO4从命令行回显时在正确的时间启动。

    如何UART4_RTSn通过调整硬件配置或更改 pyserial 中的配置来更改引脚的极性?

    这让我想到了第二个问题

  2. 正如我在问题 1 中所述UART4_RTSn,当像这样将值回显到 tty 端口时,该引脚将为我自动(但向后)工作:

    echo -en '\x02\xFD\xCD......' > /dev/ttyO4
    

    这将使UART4_RTSnLED 在数据传输时闪烁。如果我在没有上面提到的骨文的情况下设置它,那么它将正常打开并在传输时闪烁。如果我使用我的bonescript hack,那么它将正常关闭并在传输时闪烁(这是我想要的)。但是,这仅在从命令行使用 echo 时有效。当我使用 python 并设置串行端口时,UART4_RTSn引脚变为非活动状态。发射时不会闪烁。一旦我在python中发表声明:

    ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
    

    UART4_RTSn销关闭并保持关闭。使用 发送信息时不闪烁ser.write(stuff)。因此,rs485 板未启用传输。如何让UART4_RTSnpin 在 pyserial 中自动工作?我试过设置rtscts=False,但没有用。

    我可以使用ser.setRTS(True)ser.setRTS(False)手动切换引脚值,因此我知道我使用了正确的引脚并且它正在被识别。但我不想直接切换 UART4_RTSn 引脚。我希望它在串行端口传输数据时自动工作,并且在使用 echo 时它会自动工作,但在 Python 中不会。

任何帮助将不胜感激。

4

3 回答 3

1

RTS 通常是低电平有效信号,我怀疑您看到正在传输的数据的原因echo是它没有使用 RTS/CTS(保持高电平),因此只能传输数据。

根据http://www.raspberrypi.org/phpBB3/viewtopic.php?f=26&t=29408上的帖子

如果启用硬件流控制(“man termios”中的 CRTSCTS,或“stty crtscts -F /dev/ttyAMA0”或 pySerial rtscts=True),则仅当 CTS 被断言时才会进行发送。RTS 将被断言,除非内核输入缓冲区已满。内核输入缓冲区大约为一页或 4KB,因此您的应用程序必须在 RTS 实际更改之前远远落后于其读取。

因此,请检查 CTS 是否在您的电路板之外被断言(拉到地)。但是,我认为这不会让您正确控制所需的 RTS。

因此,对于您的应用程序,您应该禁用硬件流控制 ( ) 并在写入之前和之后rtscts=False手动控制 RTS 。setRTS(1)setRTS(0)

如果您仍然没有看到数据通过设备,请尝试交换 A 和 B 线 - A/B 标记(令人沮丧)在 RS485 设备之间不一致。如果可能,最好在您自己的应用程序中使用 D+/D- 标记。

于 2014-01-17T02:42:11.370 回答
1

使用 ioctl 更改逻辑级别...

98         struct serial_rs485 rs485conf;
 99 
100         /* Enable RS485 mode: */
101         rs485conf.flags |= SER_RS485_ENABLED;
102 
103         /* Set logical level for RTS pin equal to 1 when sending: */
104         rs485conf.flags |= SER_RS485_RTS_ON_SEND;
105         /* or, set logical level for RTS pin equal to 0 when sending: */
106         rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
107 
108         /* Set logical level for RTS pin equal to 1 after sending: */
109         rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
110         /* or, set logical level for RTS pin equal to 0 after sending: */
111         rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
112 
113         /* Set rts delay before send, if needed: */
114         rs485conf.delay_rts_before_send = ...;
于 2014-07-29T08:50:42.133 回答
0
  1. 您可以使用 pnp 晶体管/ p 沟道 mosfet/ 逻辑门不 - 像 7404 这样的逆变器

  2. 也许你必须在写操作后刷新写缓冲区 ser.write(....) ser.flush()

于 2014-01-16T22:42:21.930 回答