Сохранение 4-битного значения в середине 8-битного регистра - PullRequest
1 голос
/ 18 января 2010

Мне нужно сосчитать от 0 до 10 и сохранить эти значения в двоичном формате в ADCON0 (5: 2). Как мне указать бит 5 этого регистра? Бит 5 называется ADCON0bits.CHS3. Если я сохраню 4-битную переменную в ADCON0bits.CHS3, будут ли биты 1–3 записываться в биты 4–2 регистра?

Кроме того, есть ли 4-битные типы данных, которые я мог бы использовать?

Это все на микроконтроллере PIC.

Редактировать: мне нужно хранить 4 бита в регистре следующим образом:

unsigned char count = 10 //max value
[X][X][1][0][1][0][X][X]

Это соответствует тому, что предполагалось ниже, но я решил, что немного проясню свой вопрос.

Ответы [ 4 ]

4 голосов
/ 18 января 2010

Когда вы говорите, что записываете биты 1-3 вашего счета в позиции 4-2 вашего регистра, вы имеете в виду, что вы меняете порядок бит?В этом ответе я предполагаю, что это не то, что вы имели в виду.

Вы можете явно выразить битовое поле в виде структуры .Предполагая, что вы имеете дело с 16-битным регистром, ваша структура может выглядеть примерно так: struct adcon { unsigned char someflag : 2; unsigned char count : 4; unsigned char other_bits : 2; }; Для каждого члена структуры вы указываете количество битов.Затем вы можете оперировать соответствующими битами в регистре, приведя регистр к типу структуры и оперируя членами структуры.на основе обратной связи, спасибо.

3 голосов
/ 18 января 2010

Запись в битовую переменную сохраняет значение истинности этой переменной в бит. Например, написание:

ADCON0bits.CHS3 = 3;

установит этот бит в 1.

Если бит 5 относится к биту, маскированному 0x20 (00100000), и вам необходимо сохранить 4-битное число в битах, маскированных 0x3c (00111100), то вы можете использовать битовые сдвиги и побитовые операции:

// First clear bits 1-5:
ADCON0 &= ~0x3c;

// Now set the bits to correct value:
ADCON0 |= (count << 2); // <-- remember to shift 2 bits to the left

обновление : как упомянуто Ианом в комментариях. Это устанавливает ADCON0 в промежуточное значение перед обновлением. В этом случае все в порядке, поскольку он только выбирает канал A / D и фактически не выполняет преобразование. Но в целом лучше сделать:

unsigned char temp_adcon;

temp_adcon = ADCON0 & ~0x3c;
ADCON0 = temp_adcon | (count << 2);
2 голосов
/ 18 января 2010

См. Ответы на этот вопрос .

Обратите внимание, что вы выполняете операцию чтения-изменения-записи. При этом вы должны быть осторожны с условиями гонки. Условия гонки могут быть вызваны:

  • Аппаратное обеспечение самостоятельно изменяет биты в регистре (например, операция аналого-цифрового преобразователя завершается и устанавливает флаги). Конструкция оборудования должна предоставить вам возможность избежать этой проблемы - есть несколько возможных решений - прочитайте руководство для микро / периферийных устройств, чтобы узнать.
  • Ваша собственная подпрограмма (ы) прерывания, также записывающая в регистр. Если это так, когда ваш основной (не прерываемый) код записывает данные в регистр, это следует делать в контексте «прерывания отключены».
1 голос
/ 18 января 2010

Я не уверен насчет точного регистра ADCON0, но часто вы можете прочитать регистр, замаскировать 4 бита и вставить свой счетчик, а затем использовать это значение для обратной записи в регистр.

На всякий случай маскирование выполняется с помощью операции И, а вставка - это операция ИЛИ со смещением счетчика более чем на 2 бита в вашем случае.

...