1

我有一个 Arduino Duemilanove 设置,可以通过串行 TX 端口发送一个基本的字符串。在另一端,我有一个 iPhone 设置,可以通过坞站连接器中的串行端口接收消息。

当我运行以下命令时cat /dev/tty.iap 9600,我看到 Arduino 发送的消息被打印在终端窗口上。消息Hello iPhone正在通过 while 循环发送,该循环在屏幕上重复打印消息。

因此,当我尝试在我正在开发的 iPhone 应用程序中阅读消息时,我的问题就开始了。我为应用程序中的基本串行控制台组合了一个简单的 GUI,我得到了如下字符,

带有按钮的覆盖层在那里,因为物理主页按钮不起作用。

基本 iPhone 串行控制台

我正在使用从本教程中找到的代码打开串行端口

串行接口文件如下所示,

JailbrokenSerial.h

#import <Foundation/Foundation.h>
#include <termios.h> /* POSIX terminal control definitions */

@protocol JailbrokenSerialDelegate
- (void) JailbrokenSerialReceived:(char)ch;
@end

@interface JailbrokenSerial : NSObject {
    NSThread *thread;
   __unsafe_unretained id<JailbrokenSerialDelegate> _receiver; // added "__unsafe_unretained" because of SO thread
    int fd;
    struct termios gOriginalTTYAttrs;
    BOOL debug;                         // will print debugging message if YES
    BOOL nonBlock;                      // will act as nonblocking mode. delegate 'receiver' required
    char receivedCh;
}

@property (nonatomic, assign) id<JailbrokenSerialDelegate> receiver;
@property (nonatomic, assign) BOOL debug;
@property (nonatomic, assign) BOOL nonBlock;

- (id)initWithReceiver:(id<JailbrokenSerialDelegate>) receiver;

- (BOOL)open:(int)baudRate;
- (BOOL)isOpened;
- (void)close;
- (ssize_t)read:(void *)buffer length:(size_t)len;
- (void)write:(const char *)message length:(int)len;
- (void)write:(NSString *)message;
@end

JailbrokenSerial.m

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */

#include <sys/ioctl.h>

#import "JailbrokenSerial.h"

@interface JailbrokenSerial ()
- (void)readPoller;
@property (nonatomic, retain) NSThread *thread;
@end

@implementation JailbrokenSerial

//@synthesize receiver = _receiver;
@synthesize debug, nonBlock;
@synthesize thread;

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
        fd = -1;
        debug = false;
        nonBlock = false;
        self.thread = nil;
    }

    return self;
}

- (id)initWithReceiver:(id<JailbrokenSerialDelegate>) receiver {
    self = [self init];
    if(self) {
        [self setReceiver:receiver];
    }

    return self;
}

- (void)dealloc {
    [thread cancel];
    //[thread release];

   // [super dealloc];
}

- (void)readPoller {
    //  // Top-level pool
    char ch;
    int buf_len;

   // NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];

    while(![[NSThread currentThread] isCancelled]) {

        buf_len = read(fd,&ch,1); // Read 1 byte  over serial.  This will block
        //        NSLog(@"Loop");

        // If something can be read
        if(buf_len == 1) {
            receivedCh = ch;
            [self performSelectorOnMainThread:@selector(sendReadMessage) withObject:nil waitUntilDone:YES];
        }
        else if(buf_len == -1) {
            [NSThread sleepForTimeInterval:0.1]; // set the wait time for the read loop - IMPORTANT
        }
        [myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
    }
    //[pool release];
}

- (void)sendReadMessage {
    [self.receiver JailbrokenSerialReceived:receivedCh];
}

- (ssize_t)read:(void *)buffer length:(size_t)len {
    return read(fd, buffer, len);
}

- (BOOL)open:(int)baudRate {
    struct termios  options;

    int fileDescriptor = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NONBLOCK);
    //    int fileDescriptor = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fileDescriptor == -1)
    {
        if(debug) NSLog(@"Error opening serial port %@ - %s(%d).", @"/dev/tty.iap", strerror(errno), errno);
        close(fileDescriptor);
        return false;
    }

    if(ioctl(fileDescriptor, TIOCEXCL) == -1) {
        if(debug) NSLog(@"Error setting TIOCEXCL on %@ - %s(%d).", @"/dev/tty.iap", strerror(errno), errno);
        close(fileDescriptor);
        return false;
    }

    if(nonBlock) {
        if(fcntl(fileDescriptor, F_SETFL, O_NONBLOCK) == -1) {
            if(debug) NSLog(@"Error setting O_NONBLOCK on %@ - %s(%d).", @"/dev/tty.iap", strerror(errno), errno);
            close(fileDescriptor);
            return false;
        }
    }
    else {
        if(fcntl(fileDescriptor, F_SETFL, 0) == -1) {
            if(debug) NSLog(@"Error clearing O_NONBLOCK on %@ - %s(%d).", @"/dev/tty.iap", strerror(errno), errno);
            close(fileDescriptor);
            return false;
        }
    }
    tcgetattr(fileDescriptor, &gOriginalTTYAttrs);

    options = gOriginalTTYAttrs;

    if(debug) {
        NSLog(@"Current input baud rate is %d\n", (int) cfgetispeed(&options));
        NSLog(@"Current output baud rate is %d\n", (int) cfgetospeed(&options));
    }

    // Set raw input (non-canonical) mode, with reads blocking until either a single character
    // has been received or a one second timeout expires.
    // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
    cfmakeraw(&options);
    options.c_cc[VMIN] = 1;
    options.c_cc[VTIME] = 10;

    // The baud rate, word length, and handshake options can be set as follows:

    cfsetspeed(&options, baudRate);    // Set 19200 baud
    options.c_cflag &= ~PARENB;      // Set as 8-1-N
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    if(debug) {
        NSLog(@"Input baud rate changed to %d\n", (int) cfgetispeed(&options));
        NSLog(@"Output baud rate changed to %d\n", (int) cfgetospeed(&options));
    }

    tcsetattr(fileDescriptor, TCSANOW, &options);

    fd = fileDescriptor;

    if(nonBlock) {
        self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(readPoller) object:nil];
        [thread start];
    }

    return true;
}

- (BOOL)isOpened {
    if(fd==-1)
        return false;
    else
        return true;
}

- (void)close{
    if(fd != -1) {
        close(fd);
        fd = -1;
        [thread cancel];
        self.thread = nil;

        if(debug)
            NSLog(@"Closed");
    }
}

- (void)write:(const char *)message length:(int)len {
    if(fd != -1) {
        write(fd, message, len);
    }
    if(debug) {
        NSLog(@"%d bytes wrote", len);
    }
}

- (void)write:(NSString *)message {
    [self write:[message UTF8String] length:[message length]];
}


@end

我像这样在串行控制台视图控制器中打开串行端口,

ViewControllerSerialConsole.h

#import <UIKit/UIKit.h>
// #import "Serial.c"
#import "JailbrokenSerial.h"

#define BUFFER_LEN 1024

@interface ViewControllerSerialConsole : UIViewController <JailbrokenSerialDelegate> {
    JailbrokenSerial *serial;


    UInt8 rxBuffer[BUFFER_LEN];
    UInt8 txBuffer[BUFFER_LEN];

}
@property (weak, nonatomic) IBOutlet UITextField *textEntry;
@property (weak, nonatomic) IBOutlet UIButton *btnSend;
@property (weak, nonatomic) IBOutlet UITextView *serialView;
/*
@property (weak, nonatomic) IBOutlet UIToolbar *btnOpen;
@property (weak, nonatomic) IBOutlet UIToolbar *btnClose;
@property (weak, nonatomic) IBOutlet UIToolbar *btnDone;
 */

- (IBAction)donePressed:(id)sender;
- (IBAction)sendString:(id)sender;
- (IBAction)openSerial:(id)sender;
- (IBAction)closeSerial:(id)sender;


@end

ViewControllerSerialConsole.m

#import "ViewControllerSerialConsole.h"

@interface ViewControllerSerialConsole ()

@end

@implementation ViewControllerSerialConsole
@synthesize textEntry = _textEntry;
@synthesize btnSend = _btnSend;
@synthesize serialView = _serialView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewDidUnload
{
    [self setTextEntry:nil];
    [self setBtnSend:nil];
    [self setSerialView:nil];
    /*
    [self setBtnOpen:nil];
    [self setBtnClose:nil];
    [self setBtnDone:nil];
     */
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)donePressed:(id)sender
{
    [self dismissModalViewControllerAnimated:YES];    
}

- (IBAction)sendString:(id)sender {
    // dismiss keyboard
    [self.textEntry resignFirstResponder];
}

- (IBAction)openSerial:(id)sender
{
    serial.debug = YES; // debug messaages will be printed out using NSLog() if the flag is set to YES

    [serial open:B9600];
    NSLog(@"%c", [serial isOpened]);

    serial.nonBlock = true;

    serial.receiver = self;

    char buffer[12];
    [serial read:buffer length:12]; // will be blocked until read 5 characters.

    // print line to textview
    _serialView.text = [NSString stringWithFormat:@"%s",buffer];

}

- (IBAction)closeSerial:(id)sender
{
    [serial close];
}

@end
4

1 回答 1

0

我从分线板上取下了所有电线,并重新焊接了所有连接,这似乎解决了我的问题:)

于 2013-04-07T19:21:38.513 回答