我正在尝试使用运行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_RTSn
和UART4_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)
我知道该程序有效,因为当我在/dev/ttyUSB0
上使用USB转RS-485转换器并设置rtscts=False
时,通信在两个方向都可以正常工作。但是我无法使用RS-485板正常工作。
我在RS-485板上遇到两个问题,两者都处理RTS。
电路板上的RTS从我期望的方式向后工作。当我在rs485板的RTS引脚上施加电压时,电路板上的RTS指示灯熄灭,电路板不会发送。当我从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
时正确的时间出现。
如何通过调整硬件配置或更改pyserial中的配置来更改UART4_RTSn
引脚的极性?
这让我想到了第二个问题
正如我在问题1中所说的那样,当我向tty端口回显一个值时,UART4_RTSn
引脚将自动(但向后)工作:
echo -en '\x02\xFD\xCD......' > /dev/ttyO4
这将使UART4_RTSn
指示灯在传输数据时闪烁。如果我没有上面提到的bonescript进行设置,那么它将正常启动并在传输时闪烁。如果我使用我的bonescript hack那么它会正常关闭并在传输时闪烁(这就是我想要的)。但是,这仅在从命令行使用echo时才有效。当我使用python并设置串口时,UART4_RTSn
引脚变为非活动状态。传输时不会闪烁。一旦我在python中发表声明:
ser = serial.Serial('/dev/ttyO4', baudrate=9600, rtscts=True)
UART4_RTSn
引脚关闭并保持关闭状态。使用ser.write(stuff)
发送信息时不会闪烁。因此,rs485板无法进行传输。如何让UART4_RTSn
引脚在pyserial中自动运行?我已经尝试设置rtscts=False
但它没有用。
我可以使用ser.setRTS(True)
或ser.setRTS(False)
手动切换引脚值,因此我知道我正在使用正确的引脚并且正在识别它。但我不想直接切换UART4_RTSn引脚。我希望它在串口传输数据时自动工作,而在使用echo时则自动工作,但在Python中则不行。
非常感谢任何帮助。
答案 0 :(得分: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
)并在写入之前使用setRTS(1)
手动控制RTS,然后再setRTS(0)
。
如果您仍然没有看到数据通过设备,请尝试更换A&amp; B线 - 在RS485设备上(令人沮丧地)A / B标签不一致。如果可能,最好在自己的应用程序中使用D + / D-标记。
答案 1 :(得分: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 = ...;
答案 2 :(得分:0)
你可以使用pnp晶体管/ p沟道mosfet /逻辑门不 - 逆变器如7404
也许你必须在写操作后刷新写缓冲区 ser.write(....) ser.flush()