Я вообще не парюсь, делаю приведение типа исходного значения к
массиву байт и работаю как с массивом: typedef struct __attribute__((packed)) {
int Int24 :24; //Честное знаковое 24-битное значение, чтобы компилятор мог пожаловаться на возможное переполнение
} Int24_t; //Размер 3 байта
int32_t Int24to32(Int24_t Int24) {
uint8_t *Ptr = (uint8_t*) &Int24; //Указатель на байты аргумента
uint32_t Result = Ptr[0]; //Младший байт
Result |= (uint16_t) Ptr[1] << 8; //Средний байт
Result |= (uint32_t) Ptr[2] << 16; //Старший байт
if (Ptr[2] & 0b10000000) { //Проверка знака
Result |= (uint32_t) 0xFF << 24; //Установка знака "минус"
}
return (int32_t) Result;
}
Типа того. Это для ARM Cortex. Для других индейцев нужно иначе.
То же самое и при получении или передаче байт в SPI. Например, средний байт: ((uint8_t*)&Int24_t)[1].