2016-04-09 5 views
1

У меня есть 8-битный регистр, и я хочу изменить биты 4,5 и 6 без изменения других бит. Эти бит могут принимать значения от 000 до 111 (независимо от их предыдущего состояния). Есть ли способ изменить их за один шаг или изменить их индивидуально?Изменение более одного бита в регистре

ответ

1

Вам нужна маска, чтобы положить запрошенные биты в известного состояния, 0 является более удобно, так как в моих привычках программирования, а затем установить биты, которые вы хотите 1 с или операции и записи обратно:

#define mask 0x70 // 01110000b bit 4, 5 & 6 set 
reg = (reg & ~mask) | (newVal & mask); 

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

#define mask 0x8f // 10001111b bit 4, 5 & 6 reset 
reg = (reg & mask) | newVal; //newVal must have always bits 7, 3, 2, 1 & 0 reset. 
+0

Я не вижу, как '0' более удобно, чем' 1' для известного состояния. Речь идет только о том, включите ли вы на следующем шаге нужные вам биты (с помощью '|' операции) или выключите бит, который вы хотите отключить (с помощью операции '&'). –

+0

@JohnBollinger, я считаю более удобным 0, потому что для установки желаемых бит, как вы сказали, вам просто нужно «или» между значениями, чтобы сбросить их, вам нужно «и» значение регистра с ** перевернутым ** входное значение. Вам нужно 2 операции. –

+0

Нет, альтернатива может быть такой же сложной, как ваш пример, и она не требует инвертирования ввода: 'reg = (reg | mask) & (newVal | ~ mask)'. –

1

Вы можете сделать это с помощью операции побитового, то есть первый очистить 3 бита, а затем установить их:

unsigned char value = 0x70; 
unsigned char r = 0xFF; 
r = (r & 0x8F) | value; 
+0

Я думаю, вы имеете в виду побитовое или '' '? – Unimportant

+0

ах, действительно, да, исправлено, спасибо @ user1320881 – fluter

1

Вы можете использовать bit-field внутри структуры:

typedef struct{ 
    unsigned char b0_3 : 4; 
    unsigned char b4_6 : 3; 
    unsigned char b7 : 1; 
}your_reg_type; 

your_reg_type my_register; 

//modify only the bits you need 
my_register.b4_6 = 0x02; 

Проверьте, как ваш компилятор заказов на бит внутри структуры перед попыткой и order your bit-field accordingly

+0

этот ответ не является (обязательно) правильным, так как в C нет гарантии, что первый бит указан бит 7. Это может быть бит 0. – user3629249

+0

Вот почему я сказал «проверить цель цели ...» – simpego81

+0

Для одного байта это не вопрос верности, а скорее реализация компилятора. На самом деле даже для нескольких байтов все еще не вопрос endianness-endianness - это порядок байтов, а не порядок бит. Компилятор может накапливать биты из MSB или LSB независимо от порядка байтов. Поэтому проверьте документацию своего компилятора, а не целевую сущность. Имейте в виду, что это может измениться между разными компиляторами для одной и той же цели. – Clifford

0

Возможны несколько вариантов и вариантов (и были предложены уже), но если значение трех последовательных битов имеет смысл в себе (т. е. , это значение от 0 до 7, а не просто набор независимых флагов или контрольных битов, например), может быть полезно сохранить значение в виде простого числового диапазона от 0 до 7, а не непосредственно данных кодирования битовой позиции в пределах значения. В этом случае:

 assert(val <= 7) ; // During debug (when NDEBUG not defined) the 
          // assert trap will catch out-of-range inputs 

    reg = (reg & mask) | (val << 4) ; 

Конечно, есть некоторые небольшие затраты на оплату упрощения интерфейса таким образом (путем добавления операции сдвига), но преимущество состоит в том, что знание деталей поля регистра макет является ограниченное одним местом.

Смежные вопросы