Меню Рубрики

Установка битов на с для авр

Электроника для всех

Блог о электронике

AVR. Учебный Курс. Конфигурация FUSE бит

В прошлых статьях я советовал тебе не лезть к этим битам. И на это были свои основания, так как неправильно выставив эти биты ты можешь наглухо заблокировать контроллер для дальнейшей перепрошивки или вообще какого либо использования.

Но без знания этой особенности контроллера далеко не уедешь. Так что распишу все по порядку. У разных версий контроллеров число FUSES разное, какие то могут отсутствовать, но основные есть всегда. Вот по ним и пройдемся.

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

В Atmel AVR принята следующая нотация: сброшенный в ноль fuse bit считается активным, т.е. включенным.

Пример Бит RSTDSBL, как можно догадаться из названия, это RESET DISABLE. Включил эту опцию и у тебя нога RESET превращается в порт ввода-вывода, но за это ты теряешь возможность перешить контроллер через ISP.

Так вот, чтобы выключить RESET (и получить большое западло с прошивкой в обмен на мелкую подачку в виде дополнительной ножки) в этот бит надо записать 0.

С одной стороны нелогично и криво. Как бы во всем мире принята нотация, что ноль это выключено, а тут, понимаешь, наоборот. С другой стороны, это их контроллер, что хотят то и делают. Один раз запомнить и все. Да и вообще, в электронике часто за сигнал берут ноль.

Однако контроллеры делают электронщики, а прошивающие программы — программисты. Как бы логично. И вот эти программисты взяли и заварили адскую путаницу с галочками. Нет бы им раз и навсегда принять за стандарт, что галочка это 1, а не ВКЛЮЧЕНО (что, напомню, является нулем). И поэтому в одних прошивающих программах галочка означает, что опция включена (в FUSE бит записывается 0),в других, обычно написанных электронщиками, галочка означает единицу. Т.е. с точностью до наоборот.

А что будет если перепутать? А будет ОЧЕНЬ плохо. Контроллер войдет в неправильный режим и может заблокируется наглухо. Т.е. раз прошил и все. Приехал.

Нет, спасти его можно, но для этого тебе потребуются дополнительные ухищрения в виде высоковольтного программатора, JTAG адаптера или генератора тактов. Все зависит от того в какой режим ты загонишь контроллер своими неправильными настройками.

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

Конфигурация тактового сигнала
По умолчанию все контроллеры AVR (кроме старых серий AT90S2313, AT90S8535 итд) сконфигурированы так, чтобы работать от внутреннего источника тактов. Т.е. стоить подать на них питание и они начинают работать. Ничего больше и не нужно.

За источник тактов отвечают биты CKSEL
Выставив их правильным образом можно выбрать частоту работы контроллера, а также источник тактового сигнала.

  • CKSEL3…0 = 0000 — Внешний источник сигнала.

Т.е. на вход XTAL1 подаются прямоугольные импульсы. Такое иногда делают в синхронных системах, когда несколько контроллеров работают от одного генератора.

Техническое отступление
В этот режим часто попадают, когда пытаются выставить контроллер на работу от внешнего кварца (CKSEL=1111), но либо путают нотацию, либо из-за прикола с обратной нотацией битов во всяких извратских прошивающих программах. Раз и кристалл заблокировался. Но, на самом деле, наглухо, с помощью CKSEL, заблокировать кристалл нельзя. Обычно все решается напайкой кварца и запуском от этого кварца. Худшее же что может случиться — потребуется внешний генератор тактов. Который бы оживил кристалл. Делается он за пять минут из любой микросхемы ТТЛ логики, например из К155ЛА3 — схем в инете навалом. Или на таймере 555, либо можно взять второй МК и на нем написать простую программку, дрыгающую ножкой. А если есть осциллограф, то с него можно поиметь сигнал контрольного генератора — его клемма должна быть на любом осциле. Землю осцила на землю контроллера, а выход генератора на XTAL1.

Но что делать если зуд нестерпимый, контроллер залочен, а никакой микросхемы для реанимации под рукой нету? Тут иногда прокатывает метод пальца. Прикол в том, что на тело человека наводится весьма нефиговая наводка частотой примерно 50Гц. Всякий кто хватался за щупы осциллографа руками помнит какие шняги тут же возникают на экране — вот это оно! А почему бы эту наводку не заюзать как тактовый сигнал? Так что припаиваешь к выводу XTAL1 провод, хватаешься за него рукой, и жмешь на чтение или запись контроллера 🙂 Предупреждаю сразу, метод работает через жопу, далеко не с первого раза, читает долго и порой с ошибками, но на перезапись FUSE битов в нужную сторону должно хватить. Пару раз у меня такой фокус получался.

CKSEL3…0 = 0100 – 8 MHz от внутреннего генератора(обычно по умолчанию стоят такие)
Для большинства AVR такая конфигурация CKSEL означает тактовку от внутреннего генератора на 8Мгц, но тут могут быть варианты. Так что в этом случае втыкай внимательно в даташит. В табличку Internal Calibrated RC Oscillator Operating Modes

Иногда нужно иметь внешний тактовый генератор, например, чтобы его можно было подстраивать без вмешательства в прошивку. Для этого можно подключить RC цепочку, как показано на схеме и подсчитать частоту по формуле f = 1/3RC, где f будет частотой в герцах, а R и С соответственно сопротивлением резистора и емкостью конденсатора, в омах и фарадах.

  • CKSEL3…0 = 0101 – для частот ниже 0.9 MHz
  • CKSEL3…0 = 0110 – от 0.9 до 3 MHz
  • CKSEL3…0 = 0111 – от 3 до 8 MHz
  • CKSEL3…0 = 1000 – от 8 до 12 MHz

Данная табличка справедлива только для ATmega16 у других МК может отличаться. Уточняй в даташите!

Проблема у внутреннего генератора и внешних RC цепочек обычно в нестабильности частоты, а значит если сделать на ней часы, то они будут врать, не сильно, но будут. Поэтому иногда полезно запустить контроллер на кварце, кроме того, только на кварце можно выдать максимум частоты, а значит и производительности проца.

  • CKSEL3…0 = 1001 — низкочастотный «часовой» кварц.

На несколько десятков килогерц.
Используется в низкоскоростных устройствах, особенно когда требуется точная работа и низкое потребление энергии.

Для обычных кварцев ситуация несколько иная. Тут максимальная частота кварца зависит также и от бита CKOPT когда CKOPT = 1 то:

  • CKSEL3…0 = 1010 или 1011 — от 0,4 до 0.9 MHz
  • CKSEL3…0 = 1100 или 1101 — от 0,9 до 3 MHz
  • CKSEL3…0 = 1110 или 1111 – от 3 до 8 MHz (либо от 1 до 16Мгц при CKOPT=0)
Читайте также:  Установка газа на туарег отзывы

А если CKOPT равен 0 то при тех же значения CКSEL можно поставить кварц от 1 до 16MHz.

Разумеется, кварц на 16MHz можно поставить только на Мегу без индекса ”L”. (Хотя, как показывает практика, Lку тоже можно неслабо разогнать. У меня ATMega8535L заработала на 16Мгц, но были странные эффекты в работе. Поэтому я не стал так извращаться и разгон снял). Опять же, все выше сказанное в точности соответствует только Меге 16, у других может незначительно отличаться.

Бит CKOPT задает размах тактового сигнала. Т.е. амплитуду колебаний на выходе с кварца. Когда CKOPT = 1 то размах маленький, за счет этого достигается меньшее энергопотребление, но снижается устройчивость к помехам, особенно на высоких скоростях (а предельной, судя по таблице выше, вообще достичь нельзя. Точнее запуститься то он может запустится, но вот надежность никто не гарантирует). А вот если CKOPT активизировать, записать в него 0, то размах сигнала сразу же станет от 0 до питания. Что увеличит энергопотребление, но повысит стойкость к помехам, а значит и предельную скорость. При оверклокинге МК тем более надо устанавливать CKOPT в 0.

Также стоит упомянуть бит SCKDIV8 которого нет в Atmega16, но который часто встречается в других контроллерах AVR. Это делитель тактовой частоты. Когда он установлен, т.е. в нуле, то частота выставленная в битах CКSEL0…3 делится на 8, на чем в свое время прилично застрял Длинный, долго пытаясь понять чего это у него западло не работает. Вся прелесть в том, что этот делитель можно отключить программно, записав в регистр CLKPR нужный коэффициент деления, например один. Весь прикол в том, что SCKDIV8 активен по дефолту! Так что внимательней!

Биты SUT задают скорость старта МК после снятия RESET или подачи питания. Величина там меняется от 4ms до 65ms. Мне, за всю практику, пока не довелось эту опцию использовать — незачем. Так что ставлю на максимум 65ms — надежней будет.

Бит RSTDISBL способен превратить линию Reset в одну из ножек порта, что порой очень нужно когда на какой-нибудь крошечной Tiny не хватает ножек на все задачи, но надо помнить, что если отрубить Reset то автоматически отваливается возможность прошивать контроллер по пяти проводкам. И для перешивки потребуется высоковольтный параллельный программатор, который стоит несколько тысяч и на коленке сделать его проблематично, хотя и возможно.

Второй заподлянский бит это SPIEN если его поставить в 1, то у тебя тоже мгновенно отваливается возможность прошивать по простому пути и опять будет нужен параллельный программатор. Впрочем, успокаивает то, что сбросить его через SPI невозможно, по крайней мере в новых AVR (в старых, в AT90S*** было можно)

WDTON отвечает за Собачий таймер, он же Watch Dog. Этот таймер перезагружает процессор если его периодически не сбрасывать – профилактика зависаний. Если WDTON поставить в 0, то собаку нельзя будет выключить вообще.

BODLEVEL и BODEN — это режим контроля за напряжением. Дело в том, что при определенном пороге напряжения, ниже критического уровня, контроллер может начать сильно глючить. Самопроизвольно может запортачить, например, EEPROM или еще что откосить. Ну, а ты как думал, не покорми тебя с пару недель — тоже глючить начнешь 🙂

Так вот, для решения этой проблемы есть у AVR встроенный супервизор питания. Он следит, чтобы напруга была не ниже адекватного уровня. И если напруги не хватает, то просто прижимает RESET и не дает контроллеру стартовать. Вот эти два фуза и рулят этой фичей. BODEN включает, а BODLEVEL позволяет выбрать критический уровень, один из двух. Какие? Не буду раскрывать, посмотри в даташите (раздел System Control and Reset).

JTAGEN — Включить JTAG. По умолчанию активна. Т.е. JTAG включен. Из-за этого у MEGA16 (а также 32 и прочих, где есть JTAG) нельзя использовать вывода порта C, отвечающие за JTAG. Но зато можно подключать JTAG отладчик и с его помощью лезть контроллеру в мозги.

EESAVE — Защита EEPROM от стирания. Если эту штуку включить, то при полном сбросе МК не будет стерта зона EEPROM. Полезно, например, если в EEPROM записываются какие-либо ценные данные по ходу работы.

BOOTRST — перенос стартового вектора в область бутлоадера. Если эта галочка включена, то МК стартует не с адреса 00000, а с адреса бутсектора и вначале выполняет бутлоадер. Подробней про это было написано в статье про прошивку через лоадер.

BOOTSZ0..1 — группа битов определяющая размер бут сектора. Подробней смотри в даташите. От контроллера к контроллеру они отличаются.

Lock Bits
Это, собственно, и к фузам то отношения не имеет. Это биты защиты. Установка этих битов запрещает чтение из кристалла. Либо флеша, либо ЕЕПРОМА, либо и того и другого сразу. Нужно, только если ты продаешь свои устройства. Чтобы злые конкуренты не слили прошивку и не заказали в китае более 9000 клонов твоего девайса, оставив тебя без штанов. Опасности не представляют. Если ты заблокируешь ими кристалл, то выполни полное стирание и нет проблемы.

Характерной особенностью установленных лок битов является считываемая прошивка — в ней байты идут по порядку. Т.е. 00,01, 02, 03, 04… FF, 00… Видел такую срань? Значит не судьба тебе спереть прошивку — защищена =)

Техника безопасности
И главное правило при работе с FUSE битами — ВНИМАНИЕ, ВНИМАНИЕ и ЕЩЕ РАЗ ВНИМАНИЕ! Не выставляйте никогда FUSE не сверившись с даташитом, даже если срисовываете их из проверенного источника.

Мало ли в какой нотации указал их автор, в прямой или инверсной. Так что если повторяете какую-либо конструкцию, то перед тем как ставить фузы, проверьте то ли вы вообще ставите!

Обязательно разберитесь что означает галочка в прошивающей программе. Ноль или единицу. Включено или выключено! Стандарта нет.

Если фуз биты задаются двумя числами — старший и младший биты, то выставляются они как в даташите. Где 0 это включено.

Второе, железное, правило работы с FUSE. Запомните это навсегда и не говорите, что я не учил.

ВНАЧАЛЕ ЧИТАЕМ ТЕ ЧТО ЕСТЬ, ПОТОМ ЗАПИСЫВАЕМ ТЕ КОТОРЫЕ НАДО НАМ

Чтение — модификация — запись. ТОЛЬКО так. Почему? Да просто часто бывает как — открыл вкладку FUSE, а программатор попался тупой и сам их не считал. Как результат — у тебя там везде пустые клеточки. Довольный, выставил только те, что тебе надо SKSEL, а потом нажал WRITE. Тут то и наступает, Обычно, кабздец. Т.к. в контроллер записываются не только те, что ты изменишь, а ввобще вся секция. С теми самыми пустыми клеточками. Представь какой трешняк там будет. То то же! А потом бегут жаловаться по комментам и форумам, мол я ничего такого не трогал — оно само. Ага, щаз!

Читайте также:  Установка подшипника шкворня газ 3110

Так что, еще раз — Чтение, Модификация, Запись!

Подсказка:
Как с одного взгляда определить какого типа (прямые или инверсные) fuse биты в незнакомой прошивающей проге?
Дедуктивный метод: Нажмите чтение Fuses и посмотрите на состояние бита SPIEN Этот бит всегда активен, а если он будет сброшен, то программатор контроллер даже определить не сможет. Если SPIEN в 1 — значит фьюзы инверсные, как в PonyProg. Если ноль — значит по нотации Atmel.

193 thoughts on “AVR. Учебный Курс. Конфигурация FUSE бит”

Во-первых, респект за фокус с тактовой наводкой с тела!

> Второй заподлянский бит это SPIEN

На случай отключения этой заразы есть JTAGEN, который обычно активен по умолчанию — хотя надо признать, джитаговые средства тоже не так просты, как СПИ.

По поводу установки фузов вообще. В AVR Studio есть отличное окошко, где можно натыкать фузы визуально, а потом проверить байтовые значения — и наоборот, ввести байтовые значения, и посмотреть, что из этого получилось.

Она работает со всеми AVR в DIP корпусах, и решает следующие из вышеописанных проблем:

1. Имеет разводку для высоковольтного программирования — чип практически невозможно залочить насмерть (если конечно вообще его не убить)

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

1. Имеет встроенный управляемый источник питания чипов — любой вольтаж от минимума питания до 5 с лишним вольт. Причем референсный вольтаж для ADC может управляться отдельно, или вообще отсоединяться.

2. Цепляется к компу по СОМ-порту, и управляется из бесплатно доступного AVR Studio — включая установки вольтажа питания чипа, все его фузы (причем визуально, через чекбоксы), настройки бортового тактового генератора, итп.

3. Встроенная защита от КЗ по питанию — ага, ее можно перемкнуть, и оно просто начнет мигать лампочкой (сам не пробовал, но документация говорит, что можно).

4. Восемь лампочек и восемь кнопок, которые цепляются проводком на любой порт чипа по выбору.

5. Набортная разводка чипового UARTа на отдельный СОМ-разъем, ессно через МАХ.

Стоит все это счастье что-то в районе 2500 руб, и обычно доступно вот тут

Они принимают оплату только по безналу (что элементарно решается через Сбербанк), зато доставляют в любой регион России. Пишется письмо на shop@efo.ru с указанием, чего надо, в каком количестве, и куда отправить (надо еще указать, что заказ на физ. лицо). Получаешь счет, оплачиваешь его в сбере или еще где, и ждешь железку. Ребята работают ультра-надежно, и у них к слову обычно в наличии масса вкусного Атмеловского добра, включая чипы, которые в том же ЧиД ни за что не найти. Я там не работаю — просто это чуть ли не единственная контора, которая продает отладочные комплекты по вменяемым ценам.

Как человек, который в свое время намаялся без СТК-шки, рекомендую всем — вместо очередной мобилы потратьте 2.5-3 тысячи, и облегчите себе жизнь на порядок. Минус только один — после этого захочется уйти и дальше — тогда прямая дорога на отладчик JTAG ICE MkII, и когда он вам наконец придет, все башевские баяны про линейку ночами и проваленную сессию будут вам попросту смехотворны 🙂

Вот только я не нашел это в студии. Похоже без родного девайса (STK500 или других атмеловских) добраться до этого фуз калькулятора нельзя.

Да, добраться туда можно только через то, что поддерживает хотя бы протокол STK500 — но он открыт для всех, и я видел наколенные программаторы, которые поддерживают этот протокол. Чипы для них тоже надо прошивать, но это можно сделать через Pony Prog и иже с ним. Вот пример:

Но конечно проще и надежнее потратиться один раз на СТК.

Блин, я совсем забыл, что в Студии есть такая кнопочка «Disconnected mode». Tools->Program AVR->Connect, потом ту кнопку, и получаем тот же калькулятор на вкладках Fuses и Security, только без возможности считывания/прописывания этих битов в чип. Не забыв выбрать нужный чип на первой вкладке, натыкиваем нужную конфигурацию на своей вкладке, и смотрим значение байт внизу окна.

источник

Работа с регистрами AVR микроконтроллера на Си, битовые операции

Показаны принципы работы с отдельными битами регистра порта в AVR микроконтроллере. Подробно рассмотрены битовые операции и операции сдвига битов в языке Си. Приведены примеры установки и сброса битов в регистре порта, чтение состояния битов и их инверсии.

Для записи и чтения отдельных битов в портах микроконтроллера необходимо научиться выполнять битовые операции, уметь использовать битовые маски и выполнять запись в порт.

Структура байта

Мы знаем что один байт представляет собою 8 бит, а каждый бит это — 1 или 0, биты в байте считаются справа налево. Бит 1 является младшим, а бит 8 — старшим.

1 Байт
8 (старший бит) 7 6 5 4 3 2 1 (младший бит)

Порты, байты и биты

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

В языке Си для AVR, установка значения 1 для бита в порте — это как перевод нужного переключателя в состояние «включено». На выходе канала для указанного порта, к которому подвязан наш виртуальный выключатель, появится высокий уровень, а это в свою очередь подаст напряжение на какое-то устройство, например на светодиод, который сразу же засветится.

Названия каналов в порте микроконтроллера отсчитываются с нуля (0). Ниже приведен пример битовой структуры порта PORTD:

Регистр порта PORTD, 1 байт
Номер бита в регистре 8 7 6 5 4 3 2 1
Канал порта PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0

Аналогично по структуре выглядят и другие порты — PORTA, PORTB, DDRD, PINA.

Предустановленные значения констант PD0, PD1, PB5, PA4 (и многих других) для каждого типа AVR-микроконтроллера указаны в специальном заголовочном файле библиотеки avr-libc.

Например, чтобы вывести на экран значения всех констант из IO-файла для микроконтроллера ATmega8, содержащих сочетание символов «PD» (ищем константы для порта D, PORTD), достаточно выполнить следующую команду:

Увидим следующий результат:

Теперь, при использовании константы PD0 в своей программе на Си, вы знаете что в ней содержится число 0, а в PD3 — 3 и т.д.

Читайте также:  Установка вебасто на сузуки джимни

Операции битового сдвига

А сейчас, давайте подробно и с примерами разберемся с тем, как работают операторы битового сдвига.

Существует несколько разновидностей операций битового сдвига:

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

Операторы битового сдвига в языке программирования Си обозначаются как «>>» и » >») битов в числе с отрицательным знаком (signed) выполняется арифметический сдвиг — освободившиеся позиции слева заполняются единичками (перенос знака). Это важно помнить!

  • Bin — от слова Binary, двичная система счисления;
  • Dec — от слова Decimal, десятичная система счисления;
  • Hex — от слова Hexadecimal, шестнадцатиричная система счисления.

Для примера выполним сдвиги битов в разных числах, предварительно представив их в двоичном виде.

Для числа 1 (Dec, в десятичной системе 1) — 00000001 (Bin, в двоичной системе 0b00000001):

Сдвиг влево на один разряд выполняет умножение числа на 2, а сдвиг вправо — деление числа на 2.

Для числа 209 (Dec, в десятичной системе 209) — 11010001 (Bin, в двоичной системе 0b11010001):

  • 209 = 1110001;
  • 209 > 5 = 6 (00000110)

Для пересчета из одной системы счисления в другую в Linux удобно использовать калькулятор, об этом я уже раньше писал.

Битовые операторы в языке Си

То как двигать биты в байте мы теперь знаем, дальше разберемся с битовыми операторами в Си:

» (логическое НЕ) или инверсия — унарная операция, результат которой равен 0 если операнд равен 1, и наоборот — результат равен 1, если операнд равен 0;

  • «^» (исключающее ИЛИ, XOR) — бинарная операция, результат которой равен 1 в том случае если только один из двух операндов равен 1.
  • Рассмотрим примеры битовых операций над числами 209, 7 и их битовыми представлениями:

    1101 0001 (209)
    &

    0000 0111 (7)
    —————-
    0000 0001 (1)

    1101 0001 (209)
    |
    0000 0111 (7)
    —————-
    1101 0111 (215) 1101 0001 (209)

    —————-
    0010 1110 (46) 1101 0001 (209)
    ^
    0000 0111 (7)
    —————-
    1101 0110 (214)

    Как видите, битовые операции позволяют установить или сбросить отдельные биты числа.

    Установка битов в регистре порта

    А теперь немного практики, давайте сделаем установку 6-го бита в регистре порта PORTB что в свою очередь установит высокий уровень для канала PB5 (6-й бит в регистре). Допустим что сейчас в регистре PORTB содержится число 136, которое в битовом представлении выглядит как 10001000 (высокий уровень на каналах PB7 и PB3).

    Чтобы установить 6-й бит (1001000) мы будем использовать битовую операцию логического ИЛИ в комплексе с битовой маской.

    Что такое битовая маска? — по сути это специально подготовленное число, состоящее из требуемой конфигурации битов, которое в сочетании с некоторой операцией над битами другого числа позволяет установить или сбросить биты в последнем.

    Для получения битовой маски, при помощи которой позже будет установлен один бит, мы выполним левосторонний сдвиг битов числа 1 (00000001) на 5 разрядов:

    0000 0001 (1)
    —————-
    0010 0000 (32)

    В результате битовой операции получим число 32 (00100000), это и есть наша битовая маска. Хочу заметить что это число равняется числу 2 в 5-й степени, каждый сдвиг разряда влево умножает результат на 2.

    Теперь нам останется выполнить битовую операцию ИЛИ над текущим числом в регистре и получившимся числом-маской:

    1000 1000 (136)
    |
    0010 0000 (32)
    —————-
    1010 1000 (168)

    А теперь сравните состояние регистра перед операцией и после — все состояния битов сохранены и дополнительно установлен 6-й бит.

    Для установки 6-го бита и последующей записи числа в регистр порта PORTB (установка высокого уровня для канала PB5) в нашем примере можно использовать любую из следующих конструкций операторов, они все выполняют идентичную задачу:

    • PORTB = PORTB | 32;
    • PORTB = PORTB | (1 0000 0001 (1)
      —————-
      0001 0000 (16)

    Маска готова, получили число 16 (00010000), 2 в 4-й степени. Выполним инверсию битов:

    0001 0000 (16)

    Готово, осталось применить маску к содержимому регистра порта PORTB используя битовую операцию «&»:

    1001 1101 (157)
    &
    1110 1111 (239)
    —————-
    1000 1101 (141)

    Теперь в содержимом регистра PORTD значение 5-го бита установлено в 0 с сохранением положений остальных бит. В языке Си данные операции можно выполнить используя любую из приведенных ниже, идентичных по результату команд:

    16;

  • PORTD = PORTD & 239;
  • PORTD = PORTD &

    ( 1 0000 0001 (1)
    —————-
    0000 0100 (4)

    Теперь применим битовую операцию «&» (логическое И) к содержимому регистра PORTD и получившейся маске:

    1001 0101 (149)
    &
    0000 0100 (4)
    —————-
    0000 0100 (4)

    В результате выражения получим число 4 (0000 0100).

    В языке Си все числа которые НЕ равны «нулю» (-100, -5, 1, 500) являются логической истиной (True), а 0 — логической ложью (False).

    Результат нашего выражения — число 4, которое является логической истиной (True), а это значит что 3-й разряд регистра PORTD содержит единицу.

    Вот как будет выглядеть данное выражение из двух логических операций на языке Си:

    Такое выражение можно использовать в условных операторах (if) и операторах циклов (while), например:

    Для проверки состояния бита в регистре на ноль (0) используем такую же конструкцию, только к результату выражения применим логическую операцию инверсии «!» (логическое НЕ).

    Логическая операция «!» переворачивает значение с правды (True) на ложь (False), и наоборот. В отличие от битовой операции инверсии, которая переворачивает биты с 1 на 0 и наоборот, логическая операция инверсии оперирует с логическими значениями: правда (True) на ложь (False).

    1 = True 0 = False 122 = True (149 & (1 0000 0001 (1)
    —————-
    0010 0000 (32)

    Применим маску к содержимому регистра порта PORTD:

    1011 1010 (186)
    ^
    0010 0000 (32)
    —————-
    1001 1010 (154)

    Как видите, 6-й бит в байте регистра, который раньше был 1, сейчас установлен в 0 (101 1010). Теперь осталось записать число в регистр порта и задачу можно считать выполненной. Примеры использования такой конструкции на языке Си:

    • PORTD = PORTD ^ 32;
    • PORTD = PORTD ^ (1 >» и других, но один раз хорошо разобравшись и попробовав на практике вы всегда будете иметь понятие что и как работает, откуда берется и что содержит.

    Логические и битовые операции присутствуют во многих языках программирования, не только в Си, так что данный опыт будет вам полезен если вы также будете работать и с другими языками программирования.

    источник

    Добавить комментарий