2014-10-01 52 views
0

3是一个小型C程序,用于通过串行端口读取和写入十六进制数据。在阅读中,我没有问题,卜当我尝试写一个十六进制数据,因为这:POSIX C串行端口写入缓冲区

static const unsigned char cmdActuatorOn[] = "\x41\x54\x2B\x18\x12\x00\x12\x4B" 

我看到写功能通过串行端口只发送5个字节,所以,我想,这对于任何原因将十六进制数据切换为“0x00”字符。 下面我串口设置:

int init_port(char const *const device) 
{ 
    int descriptor, result; 
    struct termios settings; 


    descriptor = open(device, O_RDWR | O_NOCTTY); 

    result = fcntl(descriptor, F_SETFL, O_NONBLOCK); 

    result = tcgetattr(descriptor, &settings); 

    settings.c_cflag &= ~PARENB; 
    settings.c_cflag &= ~CSTOPB; 
    settings.c_cflag &= ~CSIZE; 
    settings.c_cflag |= CS8; 

    settings.c_iflag |= IGNPAR; 
    settings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | INPCK);// raw data input mode 
    settings.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);// raw data output 
    settings.c_oflag &= ~OPOST;// setting timeouts 
    settings.c_cc[VMIN] = 1; // minimum number of chars to read in noncanonical (raw mode) 
    settings.c_cc[VTIME] = 5; // time in deciseconds to wait for data in noncanonical mode (raw mode) 

    cfsetispeed(&settings, B9600); 
    cfsetospeed(&settings, B9600); 


    result = tcsetattr(descriptor, TCSANOW, &settings); 

    return descriptor; 
} 

用于写入数据的功能是:

int write_port(void const *const data, size_t const size) 
{ 
    unsigned char const *p = (unsigned char const *)data; 
    unsigned char const *const q = (unsigned char const *)data + size; 
    ssize_t n; 

    while (p < q) { 
     do { 
      n = write(port_descriptor, p, (size_t)(q - p)); 
     } while (n == (ssize_t)-1 && errno == EINTR); 
     if (n == (ssize_t)-1 && errno == EWOULDBLOCK) { 
       /* Sleep for a millisecond, then retry. */ 
       usleep(1000); 
       continue; 
     } 

     if (n == (ssize_t)-1) 
       return errno; 
     else 
      if (n < (ssize_t)1) 
        return EIO; 

     p += (size_t)n; 
    } 

    if (p != q) 
     return EIO; 

    return 0; 
} 

我打电话功能如下表写入数据:

result = write_port(cmdActuatorOn, strlen(cmdActuatorOn)); 

这项工作很好他人二进制数据:

static const unsigned char cmdGetCoordAddress[] = "\x40\x04\x2B\x02\x08\x52\x41\x9D"; 
static const unsigned char cmdReadCoordChannelAddress[] = "\x43\x12\x0B\x07\x08"; 
static const unsigned char cmdReadCoordPanId[] = "\xAF\x50\x2B\x07\x09\x52\x49\x90"; 

在这种情况下,写入函数在串行端口上写入所有正确的字节。只有cmdActuatorOn不,所以我想这是0x00的问题。

我的错误在哪里?我错了串口配置?我将它设置为使用原始模式...不正确?

非常感谢

+2

以及如何将数据写入端口? – isedev 2014-10-01 14:34:51

+0

你不写“十六进制数据”。你正在写(从你的代码的外观)*二进制*数据,你*代表*在字符串中的十六进制。这不是“十六进制数据”。 – unwind 2014-10-01 14:38:42

+0

..这个东西怎么知道有5个字符,就像@isedev暗示的那样?我希望答案不是'因为空终止符',因为,看数据.... – 2014-10-01 14:39:13

回答

2

要调用strlen()上这不是一个标准的C字符串数据。

更具体地说,您的数据有一个嵌入的'\0'字节,其中C代表“字符串结尾”。因此,strlen("\x41\x54\x2B\x18\x12\x00\x12\x4B")5。不管有多少个字节跟在\x00之后,就strlen()而言,字符串都在那里结束。

由于您实际上是在阵列的大小之后,最好使用它,即使用sizeof cmdGetCoordAddress等。请注意,如果你不能访问实际数组,那么这将不起作用,即如果数组衰减为指针,它将无法工作,然后您需要从数组声明可用的点传递大小。

由于你的阵列是全球性的,所以sizeof将工作。

所以写电话:

result = write_port(cmdActuatorOn, sizeof cmdActuatorOn); 

注意,因为这cmdActuatorOn作品声明为一个数组,虽然。如果你做的非常相似:

static const unsigned char *cmdGetCoordAddress = "\x40\x04\x2B\x02\x08\x52\x41\x9D"; 

然后名称cmdGetCoordAddressunsigned char *类型的指针,sizeof将产生特定类型的尺寸(通常为4或8个)。

+0

好吧,我知道了,所以你可以告诉我一个解决方案吗? – Mitsus 2014-10-01 15:01:27

+0

非常感谢,它现在可以工作了,我已经接受了这个答案。 – Mitsus 2014-10-01 15:06:17