为啥 ORSSerialPort serialPort:didReceiveData NSData 只有单字节?

Posted

技术标签:

【中文标题】为啥 ORSSerialPort serialPort:didReceiveData NSData 只有单字节?【英文标题】:Why does ORSSerialPort serialPort:didReceiveData NSData only have single byte?为什么 ORSSerialPort serialPort:didReceiveData NSData 只有单字节? 【发布时间】:2014-02-06 03:24:51 【问题描述】:

在我的 Arduino 中,我使用 Serial.print("blah") 将多字节数据写入串行,但在 Objective-C 中,-serialPort:didReceiveData:(由 ORSSerialPort 提供)一次只能获取 1 个字节的数据.有时,它会一次抓取 2 个字节,但绝不会全部抓取 4 个字节。这是预期的吗?如果是这样,我怎样才能让它一次接收所有 4 个字节?

阿杜诺:

void loop() 
    Serial.print("blah");
    delay(1000);

对象-C:

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data 
   NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
   NSLog(@"%@",string);

在这个方法中设置断点表明data 只保存了 1 个字节。

【问题讨论】:

【参考方案1】:

这是正常的预期行为。底层串行硬件和软件无法知道您正在等待多少字节,或者一个完整的数据包是什么样的,因此它只是在数据进入时提供数据。您必须在 Objective- 中缓冲数据C 代码。从根本上说,这非常简单。创建一个可以用作缓冲区的NSMutableData

@property (strong) NSMutableData *incomingDataBuffer;

初始化它(例如在-init):

_incomingDataBuffer = [[NSMutableData alloc] init];

那么,在你的-serialPort:didReceiveData:

- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data

   [self.incomingDataBuffer appendData:data];

   if ([self dataBufferHasCompletePacket])  // Check to see if buffer contains a complete, valid packet
       [self processReceivedDataPacket:self.incomingDataBuffer]; // Do whatever you need to do with the received data
       [self.incomingDataBuffer replaceBytesInRange:NSMakeRange(0, [self.incomingDataBuffer length]) withBytes:NULL length:0]; // Clear data buffer
   

这是一个好的开始。它有一些缺陷,即它会停止并且永远不会发现数据已经停止输入,例如损坏的数据包通过电线,然后是有效的数据包,或者串行电缆在数据包中间被拔掉。这些缺陷可以通过设计良好的数据包格式的组合来修复,包括例如唯一的标头、校验和和/或结束序列以及导致接收器重置其状态的超时。

我已经想到了一些增强功能来解决 ORSSerialPort 本身中的这个问题。在 GitHub 上的 issue 中有一些关于这些东西的讨论。如果您对此感兴趣,请随意添加有关该问题的 cmets 和建议。

【讨论】:

感谢您的解释和推荐的解决方法。我可能会尝试添加一个抽象层来缓冲“数据包”。有时间我会在 GitHub 链接中评论我对此的看法。

以上是关于为啥 ORSSerialPort serialPort:didReceiveData NSData 只有单字节?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的 ORSSerialPort.send 无法连接

使用 ORSSerialPort / Xcode 进行串行读取

Cocoa 用户界面加载问题

你应该同步运行方法吗?为啥或者为啥不?

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?