2014-10-01 9 views
0

3i've небольшая программа для чтения и записи данных Hex через последовательный порт. В чтении я не проблемы, бушель, когда я пытаюсь написать Hex данных, как это:POSIX C Последовательный порт Write Cut Buffer

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

я вижу, что функция записи отправки через последовательный порт только 5 байт ... поэтому я полагаю, что это для любого причина разрезает Hex Data с символом «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; 
} 

Я называю функцию write_data, как показано ниже:

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.

Где мои ошибки? У меня неправильная конфигурация последовательного порта? Я установил его для использования в Raw Mode ... правильно?

Большое спасибо

+2

и как вы записываете данные в порт? – isedev

+0

Вы не пишете «шестнадцатеричные данные». Вы пишете (из внешнего вида вашего кода) * двоичные * данные, которые вы * представляете * как шестнадцатеричные строки. Это не «шестнадцатеричные данные». – unwind

+0

.. и как эта вещь знает, что есть пять символов, как намекнул @isedev?Я надеюсь, что ответ не «из-за нулевого терминатора», потому что, глядя на данные ... –

ответ

2

Вы звонящих strlen() данных, которая не является стандартной строкой C.

Чтобы быть более конкретным, ваши данные имеют встроенный '\0' -byte, который в 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"; 

Тогда имя cmdGetCoordAddress относится к указателю типа unsigned char * и sizeof даст размер определенного типа (обычно 4 или 8).

+0

Хорошо, я знаю. Итак, вы можете сказать мне решение? – Mitsus

+0

Спасибо большое, он работает сейчас. Я принял этот ответ. – Mitsus

 Смежные вопросы

  • Нет связанных вопросов^_^