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

时间:2014-02-06 03:24:51

标签: objective-c arduino serial-communication orsserialport

从我的Arduino,我正在使用Serial.print(“blah”)将多字节数据写入串行,但在Objective-C中,-serialPort:didReceiveData:(由ORSSerialPort提供)仅获取此数据的1字节一时间偶尔,它会同时获取2个字节,但绝不会全部4.这是预期的吗?如果是这样,我如何让它一次接收所有4个字节?

Arduino的:

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

的OBJ-C:

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

在此方法中设置断点显示data仅保留1个字节。

1 个答案:

答案 0 :(得分:0)

这是正常的预期行为。底层的串行硬件和软件无法知道您正在等待多少字节,或者完整的数据包是什么样的,所以它只是在数据传入时提供数据。您必须在目标中缓冲数据。 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中对这些内容进行了一些讨论。如果您对这个问题感兴趣,请随时添加您对该问题的意见和建议。