【问题标题】:Hardware flow control with termios (CRTSCTS) for UART DeviceUART 设备的带 termios (CRTSCTS) 的硬件流控制
【发布时间】:2016-09-28 08:52:30
【问题描述】:

现在我正在 Udoo Neo 上通过 C++ 中的 UART 与设备通信。为此,我使用 termios 建立连接并将数据写入设备。 为此,我想使用硬件流控制并使用 termios 设置标志 (CRTSCTS)。

对于硬件流控制,我已将设备 RTS 线连接到板 CTS,并且我还通过示波器检查,如果设备还没有准备好读取,它会给我一个高电平有效。

问题是,在下面的示例中,我仍然丢失了字节,只是用数字向设备发送垃圾邮件,但是板的输出表明一切都正确写入。

我以为使用硬件流控时UART会被阻塞,这样就不会丢失任何信息。我没有正确理解这一点 - 还是代码中有错误?

感谢您的帮助

const char dev[] = "/dev/ttymxc4";

int main(int argc, char **argv) {

int fd;
struct termios t; ///< control structure for a general asynchronous interface
// edited code
tcgetattr(fd, &t);

t.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
                 INLCR | PARMRK | INPCK | ISTRIP | IXON);
t.c_oflag = 0;
t.c_cflag &= ~(CSIZE | PARENB);
t.c_cflag |= (CS8 | CRTSCTS);

// edited code 
t.c_cflag |= (CLOCAL | CREAD);

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

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

cfsetispeed(&t,B57600); /* normal shall be: B115200 Baud */

fd = ::open(dev, O_RDWR);
if (fd==-1) {
    printf("UART: cannot open file: %s\n",dev);
    return -1;
}

tcsetattr(fd,TCSANOW, &t);

// edited code
fcntl(fd, F_SETFL, 0);

int count = 0;
while (true) {

    count++;
    std::stringstream output;
    output << count << ",";

    ::write(fd, output.str().c_str(), output.str().length());
    printf("%d, writing: %s\n", fd, output.str().c_str());
    usleep(10000);
}
return 0;

}

【问题讨论】:

  • (1) termios 结构未初始化使用。 tcgetattr() 永远不会被调用。 (2) termios struct 初始化不完整。仅指定输入波特率。 CREAD 和 CLOCAL 设置不正确。 VMIN=0 和 VTIME=0 被认为是有问题的。 (3) fcntl() 缺少参数。
  • 感谢您的帮助 - 我已添加更改。 - tcgetattr(fd, &t); - t.c_cflag |= (CLOCAL | CREAD); - fcntl(fd, F_SETFL, 0);运行测试时,我仍然丢失包。当手动检查 CTS 信号(使用 ioctl)时,我看到 CTS 设置为活动/非活动,因此我什至可以通过手动检查标志来获取所有包。我只是认为这将由内核处理?
  • 编辑您的帖子以显示修改后的代码以供审核。
  • 刚刚更新了原帖,所有改动都有 // 编辑过的代码注释。现在再次感谢;)
  • 研究Setting Terminal Modes ProperlySerial Programming Guide for POSIX Operating Systems。检查每个系统调用的返回码是否有错误。例如。 tcgetattr() 在分配fd 之前执行。

标签: c++ uart flow-control termios


【解决方案1】:

参考@sawdust 的链接,硬件流控制是通过

操作的

CCTS_OFLOWCRTS_IFLOW 通过libc-doc

宏:tcflag_t CCTS_OFLOW
如果设置了该位,则启用基于 CTS 线(RS232 协议)的输出流控制。
宏:tcflag_t CRTS_IFLOW
如果设置了该位,则启用基于 RTS 线(RS232 协议)的输入流控制。

CNEW_RTSCTSCRTSCTS 通过SerProgGuide

某些版本的 UNIX 支持使用 CTS 进行硬件流控制 (清除发送)和 RTS(请求发送)信号线。如果 然后在您的系统上定义 CNEW_RTSCTS 或 CRTSCTS 常量 可能支持硬件流控制。执行以下操作 启用硬件流控制:

options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */

注意“某些版本...”和“...可能受支持。

在我的特定交叉编译工具链 (Linaro GCC 6.5-2018.12) 上,如果我对这些值进行 grep,CRTSCTS 没有记录,但已定义,CCTS_OFLOW 在很多信息文件中,但没有头文件...

libc/usr/include/bits/termios.h:
174:# define CRTSCTS  020000000000              /* flow control */

正如你在评论中所说的

...我只是认为这将由内核处理?

我看到这种现象,即使我在设备树中添加相关的 rts/cts 属性({rts,cts}-gpios uart-has-rtscts),命令stty -a -F /dev/ttyS 仍然会报告回来-crtscts 意味着 RTS/CTS 握手被禁用,所以即使没有用户空间应用程序,这似乎也不是一个简单的配置。 (内核 5.4)

【讨论】:

    猜你喜欢
    • 2019-08-29
    • 2023-03-17
    • 1970-01-01
    • 2018-03-02
    • 2023-03-25
    • 2021-09-21
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    相关资源
    最近更新 更多