2014-10-01 53 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