Mik*_*ike 4 c python linux windows serial-port
我的机器上有一个C/Python设置,我正在用串行通信进行一些测试,出于某种原因,我从来没有读过超过1个字节.
我的设置:我有一台Windows 7机器,在虚拟机箱中运行OpenSUSE.我有2个USB-RS232转换器和它们之间的适配器(所以它是从一个USB端口到另一个的循环).
在Windows方面,我能够让他们通过Python-to-Python和C-to-Python相互通信.一旦我使用Linux VM,我就可以从C(Linux)到Python(Windows)获取数据,但是当我这样做时,我只能得到1个字节.我认为我打开文件或执行Linux C代码上的读取有问题,但我不确定可能是什么问题.
Python代码(使用PySerial):
>>> import serial
>>> ser = serial.Serial(3)
>>> ser
Serial<id=0x2491780, open=True>(port='COM4', baudrate=9600, bytesize=8,
parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
>>> ser.read(5)
'Hello'
>>> ser.write("hi you")
6L
Run Code Online (Sandbox Code Playgroud)
C代码:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
int open_port()
{
int fd;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0)
perror("open_port: Unable to open /dev/ttyUSB0 - ");
else
fcntl(fd, F_SETFL, 0);
return fd;
}
int swrite(int fd, char * str)
{
int n;
n = write(fd, str, strlen(str));
if (n<0)
printf("write() of %d bytes failed\n", strlen(str));
return n;
}
int main()
{
int fd, databytes;
char buf[100] = {0};
struct termios options;
fd = open_port();
//Set the baud rate to 9600 to match
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
tcsetattr(fd, TCSANOW, &options);
tcgetattr(fd, &options);
databytes = swrite(fd, "Hello");
if(databytes > 0)
printf("Wrote %d bytes\n", databytes);
databytes = read(fd, buf, 100);
if(databytes < 0)
printf("Error! No bytes read\n");
else
printf("We read %d bytes, message: %s\n", databytes, buf);
close(fd);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我回来了:
mike@linux-4puc:~> gcc serial_com.c
mike@linux-4puc:~> ./a.out
Wrote 5 bytes
We read 1 bytes, message: h
Run Code Online (Sandbox Code Playgroud)
所以Linux-> Windows编写工作正常,python显示正确的"Hello"字符串,但由于某种原因,我只在Windows-> Linux方面得到一个字节.
有人看错了吗?
编辑:
根据我得到的反馈,我尝试了两个代码调整.听起来我无法保证所有数据都会存在,所以我尝试过:
1)睡觉
if(databytes > 0)
printf("Wrote %d bytes\n", databytes);
sleep(15); // Hack one to get the data there in time, worked
databytes = read(fd, buf, 100);
Run Code Online (Sandbox Code Playgroud)
2)一个while循环
while(1){ // Hack two to catch the data that wasn't read the first time. Failed
// this only saw 'h' like before then sat waiting on the read()
databytes = read(fd, buf, 100);
if(databytes < 0)
printf("Error! No bytes read\n");
else
printf("We read %d bytes, message: %s\n", databytes, buf);
}
Run Code Online (Sandbox Code Playgroud)
似乎循环不起作用,所以未读取的数据是否会被删除? /编辑
得到了一些好的答案并对此进行了煽动(+1 无处不在!),虽然所有答案都得出正确的结论(关于读取未获取数据),但没有任何输入真正“解决”了我遇到的问题。
这是我最终让它发挥作用的方法:
结构中的设置termios
简直要了我的命。当我设置一些标志时,我并没有设置所有标志。所以这:
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
tcsetattr(fd, TCSANOW, &options);
Run Code Online (Sandbox Code Playgroud)
改成这样:
tcgetattr(fd, &options);
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
options.c_iflag = 0; // Disable Input flags
options.c_lflag = 0; // Disable Local mode flags
options.c_oflag = 0; // Disable Output flags
options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; //Data bits per character (8)
options.c_cc[VMIN] = 50; // Wait for 50 characters or
options.c_cc[VTIME] = 50; // Wait for 5 seconds
options.c_cflag |= (CLOCAL | CREAD | HUPCL); // Ignore modem status lines,
// enable receiver,
// and hang up on last close
options.c_cflag &= ~(PARENB | PARODD); //Clearing even and odd parity
options.c_cflag &= ~CSTOPB; //Clear double stop bits
tcsetattr(fd, TCSANOW, &options);
Run Code Online (Sandbox Code Playgroud)
通过这些更改,现在我可以从 Python 编写的 C Linux 代码中获取数据。
我使用这两个来源来了解很多有关该termios
结构的选项的“事实”: