为啥 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 进行串行读取