iOS中的串行通信

时间:2012-10-11 19:38:04

标签: objective-c ios serial-port

我正在开发我的第一个应用程序。这个应用程序是使用我从RedPark获得的电缆与外部硬件进行通信。 它们提供了一个具有多种易于使用的功能的库。 现在我需要通过发送命令来要求一个带有浮点数的9 * 9表。

一个名为(void)的函数readBytesAvailable用于读取,它是事件驱动的。 起初,我使用NSMutableArray来放置表:

    for (int i=0; i<81; i++) {
        NSNumber *number = [NSNumber numberWithFloat:rxLoopBuffer[i]];
        [self.arrayRead addObject:number];
        NSLog(@"%f",[number doubleValue]);
    } 

但是从控制台来看,它只有11个数字,其余70个都是0。 我想也许我需要先获取所有81个字节,然后将它们推入数组,所以我做了一些更改:

    NSMutableData *dataRead = [[NSMutableData alloc]initWithBytes:&rxLoopBuff length:81];
    unsigned char buffer[100];
    [dataRead getBytes:buffer];
    if (!self.arrayRead) {
    [self.arrayRead removeAllObjects];
    }
    for (int i=0; i<81; i++) {
    NSNumber *number = [NSNumber numberWithFloat:buffer[i]];
    [self.arrayRead addObject:number];
    NSLog(@"%f",[number doubleValue]);
    }

但它仍然有11个数字。

有人能给我一些建议吗? 非常感谢。

更新: 通过调试,我看到read方法一次最多只读取16个字节。我正在下载同一家公司提供的新版本库,看看我能做些什么。 方法代码的一部分:

    - (void) readBytesAvailable:(UInt32)numBytes
   {
    int bytesRead; 
    BOOL res = NO;

// Read the data out
bytesRead = [rscMgr read:(rxLoopBuff+loopbackCount) length:numBytes];
rxCount += bytesRead;

    //NSLog(@"Read %i, total=%i\n", bytesRead, rxCount);
    if (this is the package I need)
    {
       //do something;
    }

   }

1 个答案:

答案 0 :(得分:0)

免责声明 - 我没有这种电缆,所以,我无法测试它,也许代码不起作用。但这只是盲目的演示我将如何做到这一点。这是启用ARC的代码。

<强> SerialPortCommunication.h

#import <Foundation/Foundation.h>

@interface SerialPortCommunication : NSObject

- (void)readBytes:(UInt32)numberOfBytes
          success:(void(^)( NSData *data ))success
          failure:(void(^)( NSData *dataReadSoFar, NSError *error ))failure;

@end

<强> SerialPortCommunication.m

#import "SerialPortCommunication.h"
#import "RscMgr.h"

#define BUFFER_SIZE 128

@interface SerialPortCommunication() < RscMgrDelegate > {
  RscMgr *_rscMgr;           // Resource Manager
  BOOL _portAvailable;       // Can we use port?
  NSMutableData *_data;      // Buffer for data
  UInt32 _totalBytesToRead;  // Number of total bytes to read

  // Success block to call
  void(^ _successBlock )( NSData *data );

  // Failure block to call
  void(^ _failureBlock )( NSData *dataReadSoFar, NSError *error );

  UInt8 *_buffer;
}

@end

@implementation SerialPortCommunication

#pragma mark - Lifecycle

- (void)dealloc {
  free( _buffer );
}

- (id)init {
  self = [super init];
  if ( self ) {
    _rscMgr = [[RscMgr alloc] init];
    [_rscMgr setDelegate:self];

    _buffer = malloc( BUFFER_SIZE * sizeof( UInt8 ) );
    // DO SERIAL PORT CONFIGURATION HERE
  }
  return self;
}

#pragma mark - Public

- (void)readBytes:(UInt32)numberOfBytes
          success:(void(^)( NSData *data ))success
          failure:(void(^)( NSData *dataReadSoFar, NSError *error ))failure {
  if ( ! _portAvailable ) {
    if ( failure ) {
      // Create some NSError that port is not available
      failure( nil, nil );
      return;
    }
  }

  if ( _data ) {
    if ( failure ) {
      // Create some NSError that port is in use
      failure( nil, nil );
      return;
    }
  }

  _failureBlock = failure;
  _successBlock = success;
  _totalBytesToRead = numberOfBytes;

  _data = [NSMutableData data];
  // Now we're waiting for delegate methods
}

#pragma mark - RscMgrDelegate

- (void)cableConnected:(NSString *)protocol {
  // From now on you can use serial port
  _portAvailable = YES;
  [_rscMgr open];
}

- (void)cableDisconnected {
  // From now on you can't user serial port
  _portAvailable = NO;

  // Ouch, we can't read, fire failure
  if ( _failureBlock ) {
    // Create NSError which describes cable disconnection
    _failureBlock( _data, nil );
  }

  // Our task ends here
  _successBlock = nil;
  _failureBlock = nil;
  _data = nil;
  _totalBytesToRead = 0;
}

- (void)portStatusChanged {
  // Check status if everything's alright and you can still user serial port
  // Set _portAvailable accordingly

  // Replace if ( NO ) with condition if port is still alright and we can read
  if ( NO ) {
    if ( _failureBlock ) {
      // Create NSError which describes status change and we can't use serial port
      _failureBlock( _data, nil );
    }

    // Our task ends here
    _successBlock = nil;
    _failureBlock = nil;
    _data = nil;
    _totalBytesToRead = 0;

    _portAvailable = NO;
  } else {
    _portAvailable = YES;
  }
}

- (void)readBytesAvailable:(UInt32)length {
  if ( ! _data ) {
    // Here no one's interested in received data
    // So you can decide if you want to save them for later use or trash them
    // We are going to trash them
    [_rscMgr read:_buffer length:MIN( BUFFER_SIZE, length )];
    return;
  }

  UInt32 bytesToRead;

  // First of all, we can't read more than our buffer size
  bytesToRead = MIN( BUFFER_SIZE, length );

  // Also it's enough to read only what user requested
  UInt32 remainingBytes = _totalBytesToRead - _data.length;
  bytesToRead = MIN( bytesToRead, remainingBytes );

  // Now read bytes
  UInt32 bytesRead = [_rscMgr read:_buffer length:bytesToRead];
  if ( bytesRead > 0 ) {
    [_data appendBytes:_buffer length:bytesRead];
  }

  if ( _data.length == _totalBytesToRead ) {
    if ( _successBlock ) {
      _successBlock( _data );
    }

    _successBlock = nil;
    _failureBlock = nil;
    _data = nil;
    _totalBytesToRead = 0;
  }
}

@end

串口使用

以下是我如何使用我的课程。

#import "SerialPortUser.h"
#import "SerialPortCommunication.h"

@interface SerialPortUser() {
  SerialPortCommunication *_serial;
}

@end

@implementation SerialPortUser

- (id)init {
  self = [super init];
  if ( self ) {
    _serial = [[SerialPortCommunication alloc] init];
  }
  return self;
}

- (void)getData {
  [_serial readBytes:81
             success:^(NSData *data) {
               // Here you have NSData with 81 bytes for sure
             }
             failure:^(NSData *dataReadSoFar, NSError *error) {
               // Here you have NSData with dataReadSoFar.length bytes only
               // read so far, because an error happens
               // And error is in NSError *error
             }];
}

@end