К примеру, у вас есть некое устройство, которое по 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 способа, надеюсь они вам пригодятся.
Есть ещё один простой способ склейки!
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Автор, а какой самый быстрый способ/лучший ? Используем CVAVR, AtmelStudio
Думаю, что проще, чем эти действия, ЦП не осуществить:
MSBLSB = MSB << 8 | LSB; А вот ASM код зависит от архитектуры, поэтому про него однозначно нельзя сказать.
Спасибо за статью. С двумя байтами всё понятно стало.
А как принять и склеить 32 битное число?
Мне нужно осуществить прием данных по SPI от MAX31855 (32 бит данных) и преобразовать в температуру (выделить биты D[31:18])
Спасибо.