linux串口 读取固定字节,从串口读取N个字节(Read exactly N bytes from serial port)

在Linux环境下,使用C/C++进行串口通信时,要实现阻塞读取直到接收到指定数量的字节或达到预设超时,可以使用ioctlioctl函数配合FIONREAD选项来查询可用字节数。同时,可以创建一个接收线程来组装协议单元,然后在主线程中设置超时等待队列。确保在处理串口通信时考虑超时和字节完整性,避免因数据不足或过多而引发的问题。
摘要由CSDN通过智能技术生成

从串口读取N个字节(Read exactly N bytes from serial port)

如何从串口读取N个字节? 我需要阻止我的线程,直到端口上至少有N个字节可用或预设的时间已过期。 在运行时期间,timout值和N都应该是可变的。

注意:在使用C / C ++的Linux上使用或不使用boost。

How do I read exactly N bytes from serial port? I need my thread to block until at least N bytes is available on port or a preset timout has expired. Both timout value and N should be variable during runtime.

Note: On Linux using C/C++ with or without boost.

原文:https://stackoverflow.com/questions/13930589

更新时间:2019-12-19 15:03

最满意答案

不幸的是,正如汉斯所暗示的那样,只传递字节流的通信通道通常没有任何神奇的调用来阻止字节进入协议单元 - 你必须自己做。 这并不困难。

同样的超时。 COM端口驱动程序通常具有超时,当在某个时间间隔内没有接收到任何字节时会触发该超时,但是不会超出比该字节更复杂的任何类型的协议单元。 如果我需要做类似的事情,我通常会使用一个接收字节的线程并组装协议单元对象,直到它们完整并经过完整性检查,然后将它们推送到PC队列。 另一个线程在超时时等待队列。

Unfortunately, as hinted at by Hans, comms channels that communicate only byte streams do not, as a rule, have any magic calls to block up the bytes into protocol units - you have to do it yourself. It's not that difficult.

Similarly timeouts. COM port drivers commonly have a timeout that fires when no bytes have been received for some interval, but that cannot time out any sort of protocol unit more complex than that one byte. If I need to do something like that, I typically use one thread that received bytes and assembles protocol unit objects until they are complete and sanity-checked, then pushes them to a P-C queue. Another thread waits on the queue with a timeout.

2012-12-19

相关问答

你需要使用一个ioctl ioctl(serial_fd, FIONREAD, &bytes_avail);

这个文档非常值得一读,因为这个和许多其他问题(规范与原始模式等) http://www.cmrr.umn.edu/~strupp/serial.html You need to use an ioctl ioctl(serial_fd, FIONREAD, &bytes_avail);

This document is very much worth reading, for that

...

您已经提供了一个指针作为boost::asio::async_read_until的输入而不是引用。 它应该像这样重写: boost::asio::async_read_until(

*serial_port, response_data, delimiter,

boost::bind(

&serial_comm::data_received,

this, boost::asio::placeholders::error,

boost::asio::plac

...

不幸的是,正如汉斯所暗示的那样,只传递字节流的通信通道通常没有任何神奇的调用来阻止字节进入协议单元 - 你必须自己做。 这并不困难。 同样的超时。 COM端口驱动程序通常具有超时,当在某个时间间隔内没有接收到任何字节时会触发该超时,但是不会超出比该字节更复杂的任何类型的协议单元。 如果我需要做类似的事情,我通常会使用一个接收字节的线程并组装协议单元对象,直到它们完整并经过完整性检查,然后将它们推送到PC队列。 另一个线程在超时时等待队列。 Unfortunately, as hinted at b

...

如果你想传输文件,你应该把文件分成块,并在每个块上使用校验和; 然后在您重新加入另一侧的块时验证校验和。 这不是一个新问题。 其他人已经为你解决了。 您应该获得现有的可靠文件传输程序并通过串行链接运行它。 最重要的选择是rsync。 这就是GPL,因此如果您正在从事专有工作,许可证可能会阻止您使用它。 另一个不错的选择是XMODEM(或YMODEM或ZMODEM)。 我发现了带有BSD许可证的XMODEM的C实现,所以你可以肯定地使用它。 这比rsync更小更简单。 http://www.meni

...

从阅读(2)手册 ; 成功时返回读取的字节数(零表示文件结束),文件位置按此数字提前。 如果此数字小于请求的字节数,则不是错误; 这可能会发生,例如因为现在实际上可用的字节更少(可能是因为我们接近文件结束,或者因为我们正在从管道读取数据或从终端读取数据) 换句话说,由于您在写入后立即从套接字读取数据,并且您的计算机比串行端口快很多, 因此极有可能只有一个字符可供读取和read(2)仅返回该字符。 Got some good answers and incite on this (+1's all

...

这段代码几天前就已经运行了,但现在已经不存在了。 变化无常的程序行为通常表示初始化不正确或不完整。 你的termios初始化只配置波特率和字符框架,其他一切都是偶然的。 请参阅正确设置终端模式和POSIX操作系统的串行编程指南 。 您修改后的代码仍未正确解决此问题。 代码永远不会通过调用tcgetattr()函数初始化termios结构options 。 有关示例代码,请参阅我对如何从C中的串行端口打开,读取和写入的回答 options.c_lflag = 0;

这不被认为是分配termios元

...

当字节数组的大小小于8时,您将收到ArgumentException。 ToInt64方法需要一个字节数组,它可以从起始索引中获取至少8个值。 这在“异常”部分下的方法的MSDN文档中说明。 应用13字节测试的方法可以按如下方式完成: public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)

{

if (serial.BytesToRead >= 13)

{

...

while循环不一定按字符读取,但根据串行端口设备和传输速率,每次读取可能会一次返回一个字符。 我做了一些修改来修复你的while循环中的一些错误: while(1)

{

char buffer[100];

ssize_t length = read(fd, &buffer, sizeof(buffer));

if (length == -1)

{

printf("Error reading from serial port\n");

...

显示的代码在未初始化的句柄上调用GetCommState() : status = GetCommState(uart->handle, &uart_params);

激怒UB这样做。 其返回状态未经过测试。 由于这个uart_params可能包含 BS 没有用的数据。 帮自己一个忙: 永远检查所有相关函数调用的返回值(并让代码相应地行动)! 将所有那些返回或更改之后使用的数据的函数视为“相关”。 The code shown calls GetCommState() on an uninit

...

[评论太久了] 试试这段代码: char buffer[256];

memset(buffer, 0, 256);

size_t bytes_read= 0, bytes_expected = 11;

do {

ssize_t result = read(f, buffer + bytes_read, bytes_expected - bytes_read);

if (0 >= result)

{

if (0 > result)

{

perror("

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值