我正在尝试通过 rs485 串行链接与 arduino 交谈。我在我的电脑中插入了一个 USB 转串行 rs485 适配器,在 arduino 端插入了一个 max485。要开始,我只是上传了一个草图,它会发回它收到的东西。
#include <SoftwareSerial.h>
#define SSerialRX 10 //Serial Receive pin
#define SSerialTX 11 //Serial Transmit pin
#define SSerialTxControl 3 //RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
#define Pin13LED 13
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
void setup()
{
pinMode(Pin13LED, OUTPUT);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Receive);
RS485Serial.begin(300);
}//--(end setup )---
void loop()
{
if (RS485Serial.available()){
delay(100);
char x = RS485Serial.read();
digitalWrite(Pin13LED, HIGH);
digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
Serial.write(x);
RS485Serial.write(x);
Serial.flush();
delay(10);
digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
digitalWrite(Pin13LED, LOW);
delay(200);
}
}//--(end main loop )---
然后,为了测试连接,我在 pc 中运行一个 python 脚本,将一个字符写入串行端口并监听响应:
import serial
import time
PORT1 = "/dev/ttyUSB0"
try:
rs485 = serial.Serial(PORT1, 300)
while True:
print 'loop'
rs485.write('r')
time.sleep(0.5)
data = rs485.read()
if data == '\0':
print 'null'
else:
print data
time.sleep(1)
except:
rs485.close()
我第一次启动脚本时会发生这样的事情:
giulio@giulio-vaio:~$ python rs485io.py
loop
r
loop
r
loop
^C
如果我尝试再次启动脚本,它只会写:
giulio@giulio-vaio:~$ python rs485io.py
loop
null
loop
null
loop
null
^C
只有当我重新启动我的电脑(顺便说一下使用 ubuntu)时,它才会再次开始工作。如果我拔下并再次插入 USB 到串行转换器,没有任何变化,如果我重新启动 arduino,同样的故事。我用树莓派尝试了相同的配置,结果是相同的。更改usb端口不起作用,在arduino中再次上传相同的草图,没有任何反应。引脚 13 上的 LED 闪烁,因此 arduino 正在接收和发送一些东西,serial.read() 函数返回,所以有东西到达,但(第一次之后)是一个空字符'\x00'。在一个积极的情况下,重新启动后,我尝试让脚本继续运行一段时间,一切都很好,直到我点击 ctrl-c 并再次启动脚本。
这是我插入串行转换器后的 dmesg:
[ 6116.508264] usb 1-2.1.3: new full-speed USB device number 27 using ehci-pci
[ 6116.617247] usb 1-2.1.3: New USB device found, idVendor=1a86, idProduct=7523
[ 6116.617257] usb 1-2.1.3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 6116.617264] usb 1-2.1.3: Product: USB2.0-Serial
[ 6116.617694] ch341 1-2.1.3:1.0: ch341-uart converter detected
[ 6116.621498] usb 1-2.1.3: ch341-uart converter now attached to ttyUSB0
我不知道在此之后该怎么做,任何帮助将不胜感激。
编辑 :
电脑不需要重新启动,如果我卸载然后再次加载模块 ch341(处理 USB 转换器的模块),它就可以工作。我在代码顶部添加了两行:
subprocess.Popen("modprobe -r ch341".split()).wait()
subprocess.Popen("modprobe ch341".split()).wait()
我知道它并不能真正解决问题,但它确实有效。
编辑 2: 查看文档http://lxr.free-electrons.com/source/Documentation/serial/serial-rs485.txt,我尝试使用 c 中的此代码向驱动程序发送 ioctl 信号(i'我对C不好,所以请原谅我)
#include (all the libraries needed)
/* Driver-specific ioctls: */
#define TIOCGRS485 0x542E
#define TIOCSRS485 0x542F
/* Open your specific device (e.g., /dev/mydevice): */
int main(){
const char *file1 = "/dev/ttyUSB0";
const char *file2 = "output_cprog.txt";
int fd = open (file1,O_WRONLY);
if(fd < 0){
printf("%s: %s\n","error opening ttyusb",strerror( errno ) );
}
int fq = open(file2,O_WRONLY);
if( fq < 0){
printf("%s: %s\n","errore apertura file",strerror( errno ));
}
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;
// or, set logical level for RTS pin equal to 0 after sending:
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
// Set rts delay before send, if needed:
rs485conf.delay_rts_before_send = 10;
// Set rts delay after send, if needed:
rs485conf.delay_rts_after_send = 10;
int ioc = ioctl (fd, TIOCSRS485, &rs485conf);
if(ioc < 0){
printf("%i\n",ioc);
printf("ioctl error: %s\n", strerror( errno ));
}
char *character = "f\n";
write(fd,character,2);
char *buffer;
buffer = (char *) malloc(10);
read(fd, buffer, 1);
write(fq, buffer, 1);
printf("received character: %s\n",buffer[0]);
if( close(fd) < 0){
printf("%s: %s\n","error closing port",strerror( errno ));
}
if (close(fq) < 0){
printf("%s: %s\n","error closing file",strerror( errno ));
}
return 0;
}
但是编译和运行程序我看到的只是这个:
giulio@giulio-vaio:~$ ./ioctlRS485.o
-1
ioctl error: Inappropriate ioctl for device
received character: (null)
我认为,通过查看驱动程序https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c,它根本没有适当的功能来处理 ioctl。