Как отправить данные в порядке с прямым порядком байтов C - PullRequest
0 голосов
/ 03 января 2019

Я общаюсь с платой, требующей отправки 2 подписанного байта.

объяснение типа данных
enter image description here что мне нужно отправить enter image description here

Потребуется ли мне побитовая манипуляция или я могу просто отправить 16-битное целое число следующим образом?

int16_t rc_min_angle = -90; 
int16_t rc_max_angle = 120;

write(fd, &rc_min_angle, 2); 
write(fd, &rc_max_angle, 2);

Ответы [ 4 ]

0 голосов
/ 03 января 2019

Если функции с порядком байтов не доступны, просто запишите байты в порядке байтов с прямым порядком байтов.

Возможно с составным литералом .

//         v------------- compound literal ---------------v
write(fd, &(uint8_t[2]){rc_min_angle%256, ec_min_angle/256}, 2);
write(fd, &(uint8_t[2]){rc_max_angle%256, ec_max_angle/256}, 2);
//                      ^-- LS byte ---^  ^-- MS byte ---^
//        &

Я добавил &, предполагая, что write() похож на write (2) - Linux .

0 голосов
/ 03 января 2019

Если вам не нужен тип-тип, вы можете просто сделать:

#include <stdint.h>
#include <unistd.h>

/*most optimizers will turn this into `return 1;`*/
_Bool little_endian_eh() { uint16_t x = 1; return *(char *)&x; }

void swap2bytes(void *X) { char *x=X,t; t=x[0]; x[0]=x[1]; x[1]=t; }

int main()
{
    int16_t rc_min_angle = -90; 
    int16_t rc_max_angle = 120;

    //this'll very likely be a noop since most machines
    //are little-endian
    if(!little_endian_eh()){
        swap2bytes(&rc_min_angle);
        swap2bytes(&rc_max_angle);
    }

    //TODO error checking on write calls
    int fd =1;
    write(fd, &rc_min_angle, 2); 
    write(fd, &rc_max_angle, 2);
}
0 голосов
/ 03 января 2019

Чтобы отправить данные с прямым порядком байтов, вы можете просто сгенерировать байты вручную:

int write_le(int fd, int16_t val) {
    unsigned char val_le[2] = {
      val & 0xff, (uint16_t) val >> 8
    };

    int nwritten = 0, total = 2;
    while (nwritten < total) {
      int n = write(fd, val_le + nwritten, total - nwritten);
      if (n == -1)
        return nwritten > 0 ? nwritten : -1;
      nwritten += n;
    }
    return nwritten;
}

Хороший компилятор распознает, что код ничего не делает, и скомпилирует битовую манипуляцию в no-op на платформе с прямым порядком байтов. (См., Например, gcc, генерирующий тот же код для варианта с и без переворота в битах.)

Обратите внимание, что вы не должны игнорировать возвращаемое значение write() - оно не только может столкнуться с ошибкой, оно также может записать меньше, чем вы дали, в этом случае вы должны повторить запись.

0 голосов
/ 03 января 2019

int16_t имеет правильный размер, но может иметь или не быть правильным порядком байтов.Чтобы обеспечить порядок с прямым порядком байтов, используйте макросы, например, из endian.h :

#define _BSD_SOURCE
#include <endian.h>

...

uint16_t ec_min_angle_le = htole16(ec_min_angle);
uint16_t ec_max_angle_le = htole16(ec_max_angle);

write(fd, &ec_min_angle_le, 2);
write(fd, &ec_max_angle_le, 2);

Здесь htole16 означает «16-разрядный хост с прямым порядком байтов».Он преобразуется из собственного порядкового номера машины-хозяина в порядковый номер с прямым порядком байтов: если машина имеет порядковый номер с прямым порядком байтов, она переставляет байты;если он имеет порядковый номер, то это неоперация.

Также обратите внимание, что вы передаете адрес значения write(), а не сами значения.К сожалению, мы не можем встроить вызовы и написать write(fd, htole16(ec_min_angle_le), 2).

...