Преобразование короткого массива без знака в массив байтов в C

Я хочу преобразовать необработанный массив беззнаковых шорт в массив байтов, а затем прочитать его обратно. Цель состоит в том, чтобы отправить данные через буфер SPI и прочитать их на другом конце.

Пример:

Отправитель:

unsigned short array[10] = {65000, 0, 6000, 15000, 100, 50, 1000, 10, 5000, 2000};
const uint8_t *data = charArrayToByteArray(array); // <-- convert it ?
send(data, sizeof(data)); // send it

Получатель:

uint8_t buf[10];
uint8_t len = sizeof(buf);  
receive(buf, &len); 
unsigned short array[10] = arrayByteToCharArray(buf); // convert it back ?

Рабочие функции:

send(const uint8_t* data, uint8_t len); //function that sends the data
receive(uint8_t* buf, uint8_t* len); // function that receives the data

Мне нужна помощь с charArrayToByteArray() и arrayByteToCharArray(), и размер данных не может быть скомпрометирован. Спасибо!


person Tibbe    schedule 26.05.2018    source источник
comment
Используйте битовый сдвиг и маскирование.   -  person Barmar    schedule 27.05.2018
comment
Что именно для вас означает преобразование между этими типами массивов? Потому что проще всего просто прочитать байты исходного массива, передать их получателю и заставить получателя интерпретировать их как короткие целые числа. Это будет работать нормально, пока отправитель и получатель используют одно и то же представление unsigned short (что не является незначительным соображением). Для этого не требуется никакого специального преобразования, кроме пары приведений указателя.   -  person John Bollinger    schedule 27.05.2018
comment
Да, чтение в буфер - это нормально, но я не нашел никакой информации о том, как это сделать с массивом и прочитать его обратно.   -  person Tibbe    schedule 27.05.2018
comment
Кстати, создание len типа uint8_t в ваших функциях send() и receive() означает, что вы никогда не сможете отправлять или получать более 255 байтов за один вызов, что кажется немного ограничивающим. Если у вас есть возможность изменить его, вы можете заменить его на uint32_t.   -  person Jeremy Friesner    schedule 27.05.2018


Ответы (1)


Поскольку ваш массив содержит такие значения, как 65000, которые не могут быть отправлены в виде одного байта, разумно предположить, что вы собираетесь отправлять каждое значение в виде двух байтов.

Учитывая это, значения данных вообще не нужно преобразовывать; скорее только тип указателя (так что вызов send() будет компилироваться). Так что этого должно быть достаточно:

unsigned short array[10] = {65000, 0, 6000, 15000, 100, 50, 1000, 10, 5000, 2000};
const uint8_t *data = reinterpret_cast<const uint8_t *>(array);
send(data, sizeof(array));

Обратите внимание, что вызов send() указывает sizeof(array), а НЕ sizeof(data); поскольку data является указателем, его размер составляет либо 4, либо 8 байт (в зависимости от архитектуры вашего процессора) и не имеет ничего общего с количеством байтов данных, которые вы хотите отправить!

Принимающая сторона аналогична:

uint16_t buf[10];
uint8_t len = sizeof(buf);  
uint8_t * data = reinterpret_cast<uint8_t *>(buf);
receive(data, &len); 

Обратите внимание, что после возврата receive() len будет указывать количество полученных байтов, поэтому количество полученных значений uint16_t будет вдвое меньше:

int numShortsReceived = len/sizeof(uint16_t);
for (int i=0; i<numShortsReceived; i++) printf("Received short #%i = %u\n", i, buf[i]);

Еще одно замечание: приведенный выше код не обрабатывает преобразование с прямым порядком байтов/обратным порядком байтов. Если вы можете гарантировать, что и отправитель, и получатель будут работать на ЦП с одинаковым порядком байтов, это не проблема. Если OTOH вам нужно, чтобы этот код правильно работал на смешанных процессорах (т. е. с отправителем с прямым порядком байтов, отправляющим получателю с прямым порядком байтов, или наоборот), тогда вам нужно, чтобы ваш код отправки преобразовывал каждый из ваших uint16_t в сеть/обратный порядок байтов перед их отправкой (через htons()), а также для того, чтобы ваш код получения преобразовывал каждый из полученных uint16_t из сети/обратного порядка байтов в его локальный порядок байтов (через ntohs()) после их получения (но перед попыткой использовать их для чего-либо).

person Jeremy Friesner    schedule 26.05.2018
comment
Спасибо за ваш ответ, он объясняет часть отправки/получения. Но я не могу понять, как получить массив uint16_t с помощью битового сдвига. Я получаю странные значения. пример в цикле for: shortArray[i] = (data[i] << 8) | (data[i+1]); - person Tibbe; 27.05.2018
comment
плохо, должно быть shortArray[i] = (data[I*2 + 1] << 8) | (data[i*2]); - person Tibbe; 27.05.2018
comment
Битовый сдвиг не нужен; байты уже в правильном формате. - person Jeremy Friesner; 27.05.2018