Iphone串口错误

时间:2012-03-02 02:06:18

标签: iphone serial-port

我有一个运行iOS 5.0.1的越狱Iphone 4,我正试图通过Dock Connector将串行数据发送到我的Arduino。我已成功使用Minicom将数据发送到Arduino,但我似乎无法在应用程序中使用它。这是我的代码,错误在底部。

#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 <termios.h> /* POSIX terminal control definitions */

#import "ViewController.h"

static struct termios gOriginalTTYAttrs;

static int OpenSerialPort(void);

@implementation ViewController
@synthesize dataLabel, startData;
@synthesize timer;
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{


    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}


-(IBAction)startSerial:(id)sender{
    timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(targetMethod:) userInfo:nil repeats:YES];
             }



static int OpenSerialPort()
    {

        int        fileDescriptor = -1;
        int        handshake;
        struct termios  options;

        // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
        // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
        // See open(2) ("man 2 open") for details.

        fileDescriptor  = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NDELAY);

        NSLog(@"%d",fileDescriptor);


        if (fileDescriptor == -1)
        {
            printf("Error opening serial port %s - %s(%d).\n",
                   "/dev/tty.iap", strerror(errno), errno);
            goto error;
        }

        // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
        // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
        // processes.
        // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.

        if (ioctl(fileDescriptor, TIOCEXCL) == -1)
        {
            printf("Error setting TIOCEXCL on %s - %s(%d).\n",
                   "/dev/tty.iap", strerror(errno), errno);
            goto error;
        }

        // Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
        // See fcntl(2) ("man 2 fcntl") for details.

        if (fcntl(fileDescriptor, F_SETFL, 0) == -1)
        {
            printf("Error clearing O_NONBLOCK %s - %s(%d).\n",
                   "/dev/tty.iap", strerror(errno), errno);
            goto error;
        }

        // Get the current options and save them so we can restore the default settings later.
        if (tcgetattr(fileDescriptor, &gOriginalTTYAttrs) == -1)
        {
            printf("Error getting tty attributes %s - %s(%d).\n",
                   "/dev/tty.iap", strerror(errno), errno);
            goto error;
        }

        // The serial port attributes such as timeouts and baud rate are set by modifying the termios
        // structure and then calling tcsetattr() to cause the changes to take effect. Note that the
        // changes will not become effective without the tcsetattr() call.
        // See tcsetattr(4) ("man 4 tcsetattr") for details.

        options = gOriginalTTYAttrs;

        // Print the current input and output baud rates.
        // See tcsetattr(4) ("man 4 tcsetattr") for details.

        printf("Current input baud rate is %d\n", (int) cfgetispeed(&options));
        printf("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, B19200);    // Set 19200 baud    
        options.c_cflag |= (CS8);  // RTS flow control of input


        printf("Input baud rate changed to %d\n", (int) cfgetispeed(&options));
        printf("Output baud rate changed to %d\n", (int) cfgetospeed(&options));

        // Cause the new options to take effect immediately.
        if (tcsetattr(fileDescriptor, TCSANOW, &options) == -1)
        {
            printf("Error setting tty attributes %s - %s(%d).\n",
                   "/dev/tty.iap", strerror(errno), errno);
            goto error;
        }    
        // Success
        return fileDescriptor;

        // Failure "/dev/tty.iap"
    error:
        if (fileDescriptor != -1)
        {
            close(fileDescriptor);
        }

        return -1;
    }

-(void) targetMethod: (NSTimer *) theTimer {

    //dataLabel.text = @"timer running";

             int fd;
             char somechar[8];
             fd=OpenSerialPort(); // Open tty.iap with no hardware control, 8 bit, BLOCKING and at 19200 baud
    NSLog(@"%d",fd);

    dataLabel.text = [NSString stringWithFormat:@"%d",fd];

             if(fd>-1)
             {                
               //  dataLabel.text = @"got port";

                 write(fd,"*",1); // Write handshaking message over serial
                 ///////////////////////////////////////////////////////////////////////////////////////////////////
                 // After this, our device or our PC program should be strobing serial ground to gain access to the Iphone Serial Line
                 //////////////////////////////////////////////////////////////////////////////////////////////////
                 read(fd,&somechar[0],1); // Read 1 byte  over serial.  This will block (wait) untill the byte has been received
                 if(somechar[0]=='*') // Check if this byte is a "handshaking" message
                 {
                     dataLabel.text = @"handshake accepted";

                     printf("Serial connection established!\n"); // If it is, we have established a connection to the device and can freely read/write over serial!
                     while(true) // Do this forever or untill someone presses CTRL+C
                     {
                         dataLabel.text = @"in the loop";

                         read(fd,&somechar[0],1);  // Read a character over serial!

                      dataLabel.text = [NSString stringWithFormat:@"%@",somechar[0]]; // Write the character to the Terminal!!
                     }
                 }
             }

}
  @end

但我得到的错误是:

 2012-03-01 19:58:03.507 Iphone-Serial[2470:707] -1
    Error opening serial port /dev/tty.iap - Resource busy(16).

我应该重启手机吗?或以某种方式关闭串口?

谢谢, 安德鲁

1 个答案:

答案 0 :(得分:1)

您的应用必须具有root权限才能访问tty.iap。只需ssh到您的设备(以root身份),chmod 777 YourApp.app可以解决问题。只需从更简单的代码开始,获得响应并扩展越来越多。