Для ответа на необработанные данные вы, по сути, помещаете данные в uint8_t
и используете битовые маски и битовые смещения для извлечения ваших данных. Примером реализации может быть:
class MyData
{
private:
uint8_t data;
public:
MyData() : data(0) {}
MyData(uint8_t id, bool failure, uint8_t value) : data(0)
{
Id(id);
Failure(failure);
Value(value);
}
uint8_t Id()
{
return (data>>6);
}
void Id(uint8_t id)
{
data &= 0x3F;
data |= ((id&0x3)<<6);
}
bool Failure()
{
return (data & 0x20);
}
void Failure(bool failure)
{
if(failure)
{
data |= 0x20;
}
else
{
data &= 0xDF;
}
}
uint8_t Value()
{
return (data & 0x0F);
}
void Value(uint8_t val)
{
data &= 0xF0;
data|=(val&0xF);
}
};
Давайте рассмотрим пример Id,Вы хотите установить два старших разряда, битовая маска которых равна 0xC0.Конечно, вам нужно сдвинуть его на 6 битов, чтобы получить фактическое значение, в противном случае вы, например, получите 128 iso 2. Я сбросил маску, потому что на самом деле нет битов более высокого порядка, а bithsift удаляет младшие разряды.
Установка аналогична, вы хотите переопределить предыдущие данные, которые являются первой инструкцией (ox3F==00111111b
), оператор and очищает части, которые являются 0 в маске, и не касается других битов.Инструкция 2 использует оператор или для установки (ранее очищенных) старших битов в новое значение и оставляет оригиналы нетронутыми, так как младшие биты равны 0 и a|0==a
.
Другие частипохожи, надеюсь, что это поможет вам в пути ....
Итак, в итоге, извлечение означает "применение маски и сдвига битов", сохранение - "очистка битов с помощью & и сохранение битов с помощью |".Конечно, все становится сложнее, когда вы передаете многобайтовые значения (необходимо учитывать порядок байтов).