2014-02-06 6 views
1

Из моего Arduino я пишу многобайтовые данные в последовательный порт с Serial.print («blah»), но в Objective-C -serialPort:didReceiveData: (предоставляемый ORSSerialPort) получает только эти данные по 1 байт за раз. Иногда он захватывает 2 байта сразу, но никогда не все 4. Ожидается ли это? Если да, то как я могу заставить его сразу получить все 4 байта?Почему ORSSerialPort serialPort: didReceiveData NSData имеет только один байт?

Ардуино:

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 байт.

ответ

0

Это нормальное, ожидаемое поведение. Основополагающее серийное аппаратное и программное обеспечение не имеет возможности узнать, сколько байтов вы ожидаете или что представляет собой полный пакет, поэтому он просто доставляет данные по мере их поступления. Вам нужно будет буферизовать данные в объекте 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. В этом issue на GitHub есть несколько дискуссий. Не стесняйтесь добавлять свои комментарии и предложения по этому вопросу, если это вас интересует.

+0

Спасибо за объяснение и рекомендуемый подход к решению. Я могу взломать добавление слоя абстракции для буферизации «пакета». Я прокомментирую ссылку GitHub с моими мыслями об этом, когда у меня будет время. – 695Multimedia