- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我使用运行 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/
Yii::$app->runAction('new_controller/new_action', $params); 我相信这可以用来从另一个 Controller 调用 Controller Ac
这个问题类似于 this ,但我需要访问父成员(不是控制)。我不知道是否可以不使用依赖注入(inject)。 例如,我有一个父级,有一个成员调用用户,我需要从子 Controller 访问用户。 最佳
我有包含 2 个布局的根布局:- 选项面板- 绘制区域 我正在尝试的是访问 OptionsPaneController 中的 DrawAreaController 以调用其绘制方法。下面是 Optio
我的应用程序的 View Controller 层次结构设置如下: UIViewController | UITabBarController | UINavigationCo
我的应用程序的 View Controller 层次结构设置如下: UITabBarController | UINavigationController | | |
当我第一次为我目前在 Storyboard 中开发的应用程序创建基础布局时,我分两步完成: 选择我的 View Controller 并使用 Editor->Embed In->Navigation
设计要求: 显示用户可以选择的项目列表 选择一个项目后,使用后退按钮将用户带到一个新 View 。新 View 应在底部包含第一个屏幕中不存在的选项卡列表 单击选项卡中的项目时,应出现一个带有后退按钮
将父 Controller 设置为“parentCtrl as vm”,并将子 Controller 设置为“childCtrl as vmc”,以避免名称冲突,并且效果良好。 如何在子 Contro
我已经阅读了一些答案,例如关闭当前的 ViewController,但我的情况有所不同,因为我正在展示另一个 ViewController。 虽然我无法访问它的属性,但此代码显示了带有导航 Contr
如我所见,如果我们要实例化一个Model(例如,名为Post),我们只需调用: $post = new Post(); 现在,我还想实例化一个Controller(例如,名为Post,并为此 Cont
我已经疯狂地在整个网络上搜索解决我的问题的方法,但目前还没有。我的问题是我必须检查是否在 HTTP 请求中获得特定文本,该请求在一个 while 循环中,如果我这样做了,那么我应该离开循环并继续线程,
我想用this.get('controllers.pack.query');要得到App.PackQueryController在 App.PackController ,但失败了。 我认为问题是 E
我刚开始使用 Laravel。当我使用 codeigniter 或 zend 框架时,我可以将我的 Controller 组织到一个单独的目录中。例如,我可以创建“user/permission.ph
在 emberjs 前 2 我们可以从另一个 Controller 访问 Controller 或 Controller 中的任何方法 以下方式: App.get('router').get('nav
这可能是非常简单的实现,但我是 iOS 编程的新手,我似乎被卡住了。 所以,基本上,我有一个选项卡式应用程序。我决定除了标签栏之外还需要一个导航栏。为此,我放置了标签栏 Controller ,然后添
我有这个列表 Controller , define([ 'jquery', 'app' ], function ($,app) { app.controller("ListC
我有 3 个 Controller :RootController、FirstController 和 SecondController。我想从 RootController -> FirstCont
我有以下 Controller : /controllers/api/base_controller.rb /controllers/api/v1/articles_controller.rb 当为文
我是 Angular JS 的新手,尝试在另一个 Controller 中调用一个 Controller ,但出现以下错误。 ionic.bundle.js:21157 TypeError: $con
我有一个标签栏 Controller 和它的 3 个 child ,我还有另一个 View ,我制作了一个从 child 到 View Controller 的自定义转场,还有一个从 View Con
我是一名优秀的程序员,十分优秀!