Как сложить байты в единое число? Си++

К примеру, у вас есть некое устройство, которое по 8-бит шине передает контроллеру целые числа. С числами не превышающими 256 — все просто: отправил, получил. Но если число 1024 — его нужно разделить на два или более байтов и отправить контроллеру, а он должен собрать его в едино. Как же это сделать?
Число: 0xAF80   -> Отправляем: 0xAF, 0x80   -> Склеиваем: 0xAF80
1 — Способ

1
2
3
4
5
6
7
uint8_t MSB = 0; //Старший байт
uint8_t LSB = 0; //Младший байт
uint16_t MSBLSB = 0; //Результат
/**********************************/
MSB = 0xAF; //Присваиваем ст.байт
LSB = 0x80; //Присваиваем мл.байт
MSBLSB = MSB << 8 | LSB; //Склеиваем

Здесь используется сдвиг ст.байта вправо на 8, и последующее объединение «конца» числа с мл.байтом.
2 — Способ

1
2
3
4
5
6
7
uint8_t MSB = 0; //Старший байт
uint8_t LSB = 0; //Младший байт
uint16_t MSBLSB = 0; //Результат
/**********************************/
MSB = 0xAF; //Присваиваем ст.байт
LSB = 0x80; //Присваиваем мл.байт
MSBLSB = word(MSB, LSB); //Склеиваем

Самый простой вариант. Используется функция word, но она есть не во всех компиляторах.
3 — Способ

1
2
3
4
5
6
7
8
9
union
{
    uint8_t b[2]; //Младший и старший байты.
    uint16_t word; //Результат
} x;
/**********************************/
x.b[1] = 0xAF; //Присваиваем ст.байт
x.b[0] = 0x80; //Присваиваем мл.байт
... = x.word; //Искомое число типа unsigned int (uint16_t)

Этот вариант основан на объединение union, что превращает два uint8_t в uint16_t (unsigned int).
4 — Способ

1
2
3
4
5
6
7
volatile unsigned char b1 = 0xAF; //Старший байт
volatile unsigned char b2 = 0x80; //Младший байт
volatile unsigned int word; //Результат
/**********************************/
asm (" MOV %A0, %B1" : "=r"(word) : "0" (b1), "r"(b2)); //Магия асм-а
asm (" MOV %B0, %2" : "=r"(word) : "0" (b1), "r"(b2));
... = wd //Искомое число

Здесь используются великий и могучий Ассемблер. Но этот способ может работать не везде.
———
Для решения такой задачи я нашел 4 способа, надеюсь они вам пригодятся.

Вы можите оставить комментарий, или поставить трэкбек со своего сайта.

4 комментария к “Как сложить байты в единое число? Си++”

  1. Андрей:

    Есть ещё один простой способ склейки!

    1 uint8_t MSB = 0; //Старший байт
    2 uint8_t LSB = 0; //Младший байт
    3 uint16_t MSBLSB = 0; //Результат
    4 /**********************************/
    5 MSB = 0xAF; //Присваиваем ст.байт
    6 LSB = 0x80; //Присваиваем мл.байт
    7 MSBLSB = MSB * 0x100 + LSB; //Склеиваем
    8 //Умножение на байт+1 сдвигает ст.байт на 8 бит, как в первом способе,
    9 //а за тем прибавляем мл.байт. Тем самым мы производим склейку.

  2. Алексей:

    2Автор, а какой самый быстрый способ/лучший ? Используем CVAVR, AtmelStudio

    • Думаю, что проще, чем эти действия, ЦП не осуществить:
      MSBLSB = MSB << 8 | LSB; А вот ASM код зависит от архитектуры, поэтому про него однозначно нельзя сказать.

  3. Сергей:

    Спасибо за статью. С двумя байтами всё понятно стало.
    А как принять и склеить 32 битное число?
    Мне нужно осуществить прием данных по SPI от MAX31855 (32 бит данных) и преобразовать в температуру (выделить биты D[31:18])
    Спасибо.

Написать комментарий

XHTML: Вы можете использовать эти теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Bug Report
Локализовано: шаблоны Wordpress