【问题标题】:How to block until WiringPi finishes to sent serial data (UART)?在 WiringPi 完成发送串行数据(UART)之前如何阻塞?
【发布时间】:2020-09-08 09:15:34
【问题描述】:

设备说明(有关上下文,如果您对电子设备不满意,请跳过它):

对于一个简单的设备,通信是在半双工 UART 中完成的(TX 和 RX 在同一条线上),方式如下:

  • 一个引脚(写入模式)指示 UART 是发送还是接收(1:TX,0:RX)
  • 一个引脚写入线路 (TX)。
  • 从电线 (RX) 读取一个引脚。

write-mode 处于 TX(写入)时,RX 引脚处于高阻状态,TX 处于发送状态。当write-mode 处于RX(读取)时,TXpin 处于高阻状态,RXreceiving。

这只是为了说明,我不希望这里有电子问题/答案。

WiringPI 示例:

为此,我有以下示例:

#include <wiringPi.h>
#include <wiringSerial.h>

int main()
{
    wiringPiSetup ();
    auto fd = serialOpen ("/dev/ttyAMA0", 115200);
    
    pinMode(0, OUTPUT);
    
    for(size_t i=0; i<10; ++i)
    {
        digitalWrite(0, HIGH);
        serialPutchar(fd, '\x55');
        digitalWrite(0, LOW);
        delay(1000);
    }

    serialClose(fd);
}

使用示波器,我可以清楚地看到write-mode引脚在UART端发送数据之前被复位。

显然,我尝试添加一些“延迟”或空循环进行调整,但这对于 μs 时间不可靠(由于操作系统上的计时器通常精度)。

问题:

如何同步,所以write-mode引脚在UART字节发送后复位? (不超过大约 150μs 后)。

【问题讨论】:

  • 我看不出这个被标记为 c++ 的原因?对我来说看起来像普通的 c 代码。
  • 其实它不是标准的 C 语言(auto 不是用隐式 int 的 C 语义,而是作为 C++11 关键字)。重要的是这两种语言都会匹配问题。跨度>
  • 在嵌入式系统中使用 C++11 auto 是非常危险的。在几乎任何情况下使用它都是有问题的。
  • 到底什么是“写入模式”?使用 RTS/CTS 硬件握手,这些东西已经标准化了 60 多年……那么信号地呢?如果没有信号接地,将电池驱动的 Rasp 连接到固定 PC 将无法工作。
  • @AdrianMaire 哎呀,别担心。无论如何,我一直在忽略 auto` 关键字。但这会使 c 标签 IMO 无效。不应滥用语言标签来吸引更多受众。

标签: c++ c raspberry-pi uart wiringpi


【解决方案1】:

我看到了两种实现方式:

1.我现在无法对此进行测试,但您似乎可以使用

 void serialFlush (int fd) ;

根据文档“这将丢弃所有接收到的数据,或等待发送给给定设备的数据”参见http://wiringpi.com/reference/serial-library/

(编辑:重读那句话后,很明显它确实也会刷新要写入的数据,所以这个选项不可用......)

  1. 使用 tcdrain() (https://linux.die.net/man/3/tcdrain),在其中传递 serialOpen() 返回的 fd

【讨论】:

  • 确实,serialFlush 不会阻塞,只是“清除”缓冲区。
  • tcdrain 看起来很有希望(我会对其进行测试并接受/评论)
  • 这可行,但绝对不符合时序要求,它与使用定时器/调度的抖动大致相同。
  • 那是不幸的...你能使用UART端口的RTS(GPIO17)/CTS(GPIO16)引脚,还是必须坚持使用普通的GPIO?如果 RTS/CTS 引脚可用,那么您也可以尝试启用硬件抖动(毕竟,它正是针对这种用例...)
  • 好主意,我试试看。
【解决方案2】:

在文件描述符上设置阻塞。

在很多地方都可以找到如何将文件描述符操作恢复为阻塞模式。您可以使用来自this answer 的代码并执行以下操作:

set_blocking_mode(fd, 1);
serialPutchar(fd, '\x55');

之后write() inside serialPutchar 将被阻止。注意 fd 是opened with O_NONBLOCK in serialOpen()

【讨论】:

  • 你能举个例子吗?我找不到任何set_blocking_mode,也找不到serialOpen 的阻塞参数
  • 链接的答案有set_blocking_mode函数的完整实现。 neither blocking argument to serialOpen 没有阻塞参数,seralOpen 不允许您指定模式。 Could you put a working example?stackoverflow.com/questions/914463/…
猜你喜欢
  • 2015-07-19
  • 1970-01-01
  • 2018-05-08
  • 2015-05-14
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
相关资源
最近更新 更多