[FAQ] Изменение и чтение отдельных битов имеем порт J, в codevision работать с ним как PORTJ.n нельзя, поэтому для установки бита N в единицу не трогая другие биты делаем так: PORTJ = PORTJ | (1<> 1; // Меняем местами пары битов в тетрадах b = (b & 0x33) << 2 | (b & 0xCC) >> 2; // Меняем местами тетрады битов в байтах числа b = (b & 0x0F) << 4 | (b & 0xF0) >> 4; =============================================================================== // Тип, описывающий глобальные флаги программы typedef struct _SFLAGS { uint8_t KeyModePressed: 1; // Состояние клавиши MODE uint8_t KeyColorPressed: 1; // Состояние клавиши COLOR uint8_t GotoSleep: 1; // Команда "Заснуть" для основного потока (main) uint8_t RxComplete: 1; // Принята посылка в USART0 uint8_t: 4; // дополнение до 8 бит (резерв) } SFLAGS; volatile struct //flags { unsigned char Direction : 1; unsigned char SensorFree : 1; unsigned char Tick : 1; unsigned char DirChd : 1; } Flag; использование: Flag.Tick = TRUE; =============================================================================== Си для микроконтроллеров и чайников. Часть 2. Операции с переменными и регистрами микроконтроллера. § > Обзор стандартных операций с регистрами. Настало время перейти к более серьёзным операциям над регистрами и программными переменными. Управление работой микроконтроллера в большинстве случаев сводится к следующему простому набору действий с его регистрами: 1. Запись в регистр необходимого значения. 2. Чтение значения регистра. 3. Установка в единицу нужных разрядов регистра. 4. Сброс разрядов регистра в ноль. 5. Проверка разряда на логическую единицу или логический ноль. 6. Изменение логического состояния разряда регистра на противоположное. Во всех указанных действиях принимает участие оператор присваивания языка Си, записываемый в виде знака равенства. Принцип действия оператора примитивно прост - он записывает в регистр или переменную расположенную слева от него, значение того, что записано справа. Справа может находится константа, другой регистр, переменная либо состоящее из них выражение, например: A = 16; // Присвоить переменной A значение 16; A = B; // Считать значение переменной B и присвоить это значение переменной A; A = B+10; // Считать значение переменной B, прибавить к считанному значению 10, результат присвоить переменной A (значение переменной B при этом не изменяется). § > Запись и чтение регистров. Из рассмотренных примеров видно, что оператор присваивания сам по себе решает две первые задачи — запись и чтение значений регистров. Например для отправки микроконтроллером AVR байта по шине UART достаточно записать его в передающий регистр с именем UDR: UDR = 8; // Отправить по UART число 8; Чтобы получить принятый по UART байт достаточно считать его из регистра UDR: A = UDR; // Считать принятый байт из UART и переписать в переменную A. § > Установка битов регистров. Язык Си не имеет в своём составе команд непосредственного сброса или установки разрядов переменной, однако присутствуют побитовые логические операции "И" и "ИЛИ", которые успешно используются для этих целей. Оператор побитовой логической операции "ИЛИ" записывается в виде вертикальной черты - "|" и может выполнятся между двумя переменными, а так же между переменной и константой. Напомню, что операция "ИЛИ" над двумя битами даёт в результате единичный бит, если хотя бы один из исходных битов находится с состоянии единицы. Таким образом для любого бита логическое "ИЛИ" с "1" даст в результате "1", независимо от состояния этого бита, а "ИЛИ" с логическим "0" оставит в результате состояние исходного бита без изменения. Это свойство позволяет использовать операцию "ИЛИ" для установки N-ого разряда в регистре. Для этого необходимо вычислить константу с единичным N-ным битом по формуле 2^N, которая называется битовой маской и выполнить логическое "ИЛИ" между ней и регистром, например для установки бита №7 в регистре SREG: (SREG | 128) — это выражение считывает регистр SREG и устанавливает в считанном значении седьмой бит, далее достаточно изменённое значение снова поместить в регистр SREG: SREG = SREG | 128; // Установить бит №7 регистра SREG. Такую работу с регистром принято называть "чтение - модификация - запись", в отличие от простого присваивания она сохраняет состояние остальных битов без именения. Приведённый программный код, устанавливая седьмой бит в регистре SREG, выполняет вполне осмысленную работу - разрешает микроконтроллеру обработку программных прерываний. Единственный недостаток такой записи — в константе 128 не легко угадать установленный седьмой бит, поэтому чаще маску для N-ного бита записывают в следующем виде: (1< Сброс битов в регистрах. Ещё одна логическая операция языка Си – побитовое "И", записывается в виде символа "&". Как известно, операция логического "И", применительно к двум битам даёт единицу тогда и только тогда, когда оба исходных бита имеют единичное значение, это позволяет применять её для сброса разрядов в регистрах. При этом используется битовая маска, в которой все разряды единичные, кроме нулевого на позиции сбрасываемого. Её легко получить из маски с установленным N-ным битом, применив к ней операцию побитного инвертирования: ~(1< Проверка разрядов регистра на ноль и единицу. Регистры специального назначения микроконтроллеров содержат в своём составе множество битов-признаков, так называемых "флагов”, уведомляющих программу о текущем состоянии микроконтроллера и его отдельных модулей. Проверка логического уровня флага сводится к подбору выражения, которое становится истинным или ложным в зависимости от того установлен или сброшен данный разряд в регистре. Таким выражением может служить логическое "И” между регистром и маской с установленным разрядом N на позиции проверяемого бита : (REGISTR & (1< Изменение состояния бита регистра на противоположное. Эту, с позволения сказать, проблему с успехом решает логическая операция побитного "ИСКЛЮЧАЮЩЕГО ИЛИ” и соответствующий ей оператор Си, записываемый в виде символа " ^ ”. Правило "исключающего или" с двумя битами даёт "истину” тогда и только тогда, когда один из битов установлен, а другой сброшен. Не трудно убедиться, что этот оператор, применённый между битовой маской и регистром, скопирует в результат биты стоящие напротив нулевых битов маски без изменения и инвертирует расположенные напротив единичных. Например, если: reg=b0001 0110 и mask=b0000 1111, то reg^mask=b0001 1001. Таким способом можно менять состояние светодиода, подключенного к пятому биту порта A: #define LED 5 // Заменять в программе сочетание символов LED на число 5 (вывод светодиода). … PORTA ^=(1<< LED); // Погасить светодиод, если он светится и наоборот. § > Арифметика и логика языка Си. Мы рассмотрели типичный набор операций, используемый при работе с регистрами микроконтроллера. Помимо них в арсенале языка имеется ряд простейших арифметических и логических операций, описания которых можно найти в любом справочнике по Си, например: Для более подробного знакомства с операциями над переменными и языком Си в целом, рекомендую книгу "Язык программирования Си" Б. Керниган, Д. Ритчи.