gpt4 book ai didi

c++ - 与 BLDC Controller 通信时,串行读取 () 以错误号 11 终止

转载 作者:太空宇宙 更新时间:2023-11-04 09:59:34 25 4
gpt4 key购买 nike

所以我使用运行 Linux 内核的 ARM9 处理器 (i.mx28) 通过 RS232(高级协议(protocol)基于 CANOpen 协议(protocol))与 BLDC Controller 通信。发送到 Controller 的消息通常后跟一个响应。

Controller 侧连接器具有 RX、TX 和 GND,因此没有流量控制线等。 Controller 手册指出,必须不使用软件流量控制来建立连接。因此,我将端口配置为忽略 DCD(使用 CLOCAL)以及 RTS/CTS(使用 ~CRTSCTS)和软件流控制(使用 ~IXON、~IXOFF 和 ~IXANY)。

我的问题是:串口设置好后,写入正常,立即执行软复位等命令。然而,尝试阅读提到的响应会导致“Errno 11:资源暂时不可用”。当我尝试在运行终端的计算机上监视消息时,read() 返回 0 而不是 -1,因此未设置 errno。反之亦然,我尝试将 BLDC Controller 连接到所述终端并手动重新启动它以查看启动时发送的启动消息。这也很好用。

过去 3 天我一直在使用 Google 寻找类似的问题,但无济于事。在非阻塞 IO 的几种不同设置组合中,我还尝试了几种阻塞行为的方法,但这导致永远阻塞并且仍然根本不读取任何内容。

我怀疑串口是,尽管 termios 配置另有说明,仍然期待握手/流量控制,因为将系统连接到提供 RTS/CTS 线路的计算机工作正常。

int configureSerialPort() {
//Open Serial Port--------------------------------------------
int fileDescr = open("/dev/ttyS3", O_RDWR | O_NDELAY);
if (fileDescr < 0){
std::cout << "Unable to open Serial Port." << std::endl;
exit(1);
}
else std::cout << "Serial Port opened." << std::endl;
fcntl(fdSerial, F_SETFL, O_NONBLOCK);
//Configure Serial Port for B115200, 8N1---------
struct termios PortParams;
if (tcgetattr(fileDescr, &PortParams) < 0) {
std::cout << "Could not get Attributes." << std::endl;
exit(1);
}
else std::cout << "Got Attributes." << std::endl;

cfsetispeed(&PortParams, 115200);
cfsetospeed(&PortParams, 115200);

PortParams.c_cflag |= (CLOCAL | CREAD);
PortParams.c_cflag &= ~PARENB;
PortParams.c_cflag &= ~CSTOPB;
PortParams.c_cflag &= ~CSIZE;
PortParams.c_cflag |= CS8;
PortParams.c_cflag &= ~CRTSCTS;

PortParams.c_lflag &= ~(ICANON | ECHO | ECHONL | IEXTEN | ISIG);

PortParams.c_iflag &= ~(INPCK | ISTRIP | IGNPAR | PARMRK | IXON | IXOFF | IXANY);

PortParams.c_oflag &= ~OPOST;

PortParams.c_cc[VMIN] = 0;
PortParams.c_cc[VTIME] = 0;

if (tcsetattr(fileDescr, TCSANOW, &PortParams) != 0) {
std::cout << "Could not set Attributes." << std::endl;
exit(1);
}
else std::cout << "Port configured." << std::endl;
usleep(1000000);
tcflush(fdSerial, TCIFLUSH);
return fileDescr;
}

这是我目前的配置,按照我的理解应该没问题。

写入和读取由各自的系统调用完成:

wrLenSerial = write(fdSerial, &resetNode, sizeof(resetNode));
if (wrLenSerial < sizeof(resetNode)) {
std::cout << "Could not send Write Command." << std::endl;
}
else std::cout << "Reset Command sent." << std::endl;
usleep(60000);
memset(inBufSerial, '\0', sizeof(inBufSerial));
rdlenSerial = read(fdSerial, inBufSerial, (sizeof(inBufSerial) - 1));
if (rdlenSerial < 0) {
std::cout << "Read Error. " << errno << std::strerror(errno) << std::endl;
}
else if (rdlenSerial == 0) {
std::cout << "Nothing read." << std::endl;
}
else {
std::cout << "Node Response: ";
for (int i = 0; i < rdlenSerial; i++) {
int r = inBufSerial[i];
std::cout << std::hex << r << std::dec << " " << std::endl;
}
}

我真的希望这篇文章不会太长,任何想法都会受到赞赏!

最佳答案

Trying to read mentioned responses, however, results in "Errno 11: Resource momentarily unavailable".

根据您的配置,errno 11 完全符合预期。你已经做了所有可能的事情来将串行终端配置为非阻塞模式。
首先使用 O_NDELAY 选项打开串行终端。
然后修改一个(未初始化的)文件描述符以设置 O_NONBLOCK 选项。
最后,即使在非阻塞模式下这不起作用,termios 参数 VMIN 和 VTIME 都配置为零(即轮询模式)。

errno 所指的“不可用资源” 只是数据。用户缓冲区中没有可供系统调用返回的数据。

I also tried several ways of blocking behavior, this however resulted in blocking forever and still not reading anything at all.

没有实际代码,就没有什么可调试的。
您需要决定您的程序是要使用阻塞模式还是非阻塞模式。


The main program needs to simultaneously read potential input from given controller and an 8 bit value from an eeprom connected via i2c.

您不需要非阻塞模式来确保“同时”数据捕获。
读取设备的实际输入由与您的应用程序完全异步执行的内核驱动程序执行。
您的应用程序代码基本上无法控制这些输入操作实际发生的时间。
只要 UART 不报告接收器溢出错误,您就可以确信所有串行数据都已接收并最初存储在驱动程序的接收缓冲区中。
该数据最终将被复制到串行终端的缓冲区,其大小通常为 4096 字节。

从 I2C 设备读取也应该涉及系统缓冲区,但我没有看到从 EEPROM 读取数据的任何时间组件。
这是一种响应写入和读取命令的非 volatile 存储设备。

您的应用程序代码只是试图从内核缓冲区中获取数据。
EEPROM可以在程序方便的时候随时读取。
需要以足以防止系统缓冲区溢出的速率读取串行终端。

由于您的程序和 BLDC Controller 之间的通信结构为请求/响应对话框,因此请求串行终端输入,即程序仅在发送请求后才期待输入。
非阻塞模式非常适合这种情况。


改变

  fcntl(fdSerial, F_SETFL, O_NONBLOCK);

  fcntl(fileDescr, F_SETFL, 0);

会将刚刚打开的文件描述符置于阻塞模式。

替换

  PortParams.c_cc[VMIN] = 0;
PortParams.c_cc[VTIME] = 0;

用类似的东西:

  PortParams.c_cc[VMIN] = MIN(255, (sizeof(inBufSerial) - 1));
PortParams.c_cc[VTIME] = 1;

将尝试在每个系统调用中检索尽可能多的响应字节。
如果您更喜欢或需要更少的延迟,请研究 this answer

写入后的 usleep(60000); 语句应删除,或替换为对 tcdrain() 的调用。
一般来说,任何固定的延迟/休眠系统调用都是有问题的。

关于c++ - 与 BLDC Controller 通信时,串行读取 () 以错误号 11 终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57479555/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com