THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама
  • Перевод

Дешевые электронные «свечи» в последнее время, кажется, повсюду. Я не обращал на них особого внимания, пока не заметил, что на самом деле в них используется особый светодиод - со встроенным «моргательным» контроллером. Теперь-то совсем другое дело: кому не нравятся таинственные светодиоды? Полчаса спустя я уже набрал охапку мерцающих светодиодов китайского производства.

Конечно, самый интересный вопрос - как они работают? Учитывая, что стоят они буквально по несколько центов за штуку, там внутри не может быть какой-то дорогой электроники. В связи с этим возникает еще один вопрос: правда ли эти светодиоды хуже, чем многочисленные «свечи» на микроконтроллерах, схем которых полно в интернете?

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

В блоге Evil Mad Scientist недавно был рассказ о похожих светодиодах. Там было показано, как они «поют», если преобразовать изменения яркости в звук. А также - как с их помощью управлять более мощным диодом. Подобные трюки основаны на том, что светодиод потребляет больший ток в те моменты, когда контроллер зажигает его ярче. Обычный светодиод, включенный последовательно с мерцающим, показывает очень похожие изменения яркости. Иными словами, падение напряжения на добавочном резисторе изменяется пропорционально яркости.


Это я и использовал, чтобы извлечь управляющий сигнал контроллера и завести его на логический анализатор (см. схему выше). Подстройкой переменного резистора я добился того, чтобы анализатор воспринимал броски тока как «нули» и «единицы», а светодиод при этом нормально работал.


На диаграмме выше показаны изменения яркости диода в течение примерно минуты, записанные с частотой выборки 1 МГц. Заметны интервалы, когда светодиод непрерывно включен, и периоды, когда его яркость каким-то образом модулируется. Светодиод никогда не выключается надолго. Это разумно, ведь настоящая свеча тоже ярко светит большую часть времени, снижая яркость на короткие периоды мерцания.


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

Любопытно, что частота сигнала - примерно 440 Гц, как у стандартного камертона (нота Ля первой октавы - прим. перев. ). Совпадение? Или разработчик просто взял генератор из какой-то музыкальной схемы? Так что есть доля правды в рассказах о «музыкальности» этих светодиодов. Каждый «кадр» постоянной яркости составляет ровно 32 такта и длится около 72 мс. Это соответствует 13-14 кадрам в секунду.

Я написал небольшую программу для определения яркости в каждом кадре по коэффициенту заполнения ШИМ-сигнала. Программа читает поток отсчетов с логического анализатора и выводит серию вещественных чисел - по одному на каждый кадр.


График яркости в зависимости от времени наводит на некоторые мысли: изменения яркости случайны, дискретны и имеют неравномерное распределение. Кажется, существуют 16 уровней яркости, низшие 4 из которых используются очень редко. Им соответствуют только 13 из 3600 отсчетов.


Постороение гистограммы открывает всю картину: фактически используется только 12 уровней яркости. Ровно половина кадров имеет максимальную яркость, остальные значения распределены примерно поровну.

Как это может быть реализовано на аппаратном уровне? Вполне вероятно, используется генератор равномерно распределенных случайных чисел, которые пропускают через простую функцию-формирователь. Для того распределения, которое мы наблюдаем, требуется как минимум 12x2=24 дискретных уровня. Половина из них отображаются в один. Это весьма любопытно, так как генератор, скорее всего, выдает двоичные числа. Наиболее логичной была бы разрядность числа 5 бит, а это 32 состояния. Отобразить 32-уровневую дискретную случайную величину в 24 уровня, не изменив распределения, не так просто, как кажется. Не забываем также, что это совсем не критичная схема, и у разработчика, вероятно, не было много времени на красивое решение. Поэтому он применил самое простое, своего рода хак.

Единственный простой способ, что приходит на ум - просто отбрасывать неподходящие значения и брать следующее случайное число. Нежелательные значения можно легко отделить по битовой маске. Так как схема синхронная, есть только конечное число попыток, пока не начнется следующий кадр. Если контроллер не уложился в заданное количество попыток, он застрянет на «неправильном» значении. Помните редкие выбросы на графике яркости?

Реализация на ANSI-C могла бы выглядеть так:
char attempts=0; char out; while(attempts++15) out=15; // верхняя половина диапазона соответствует максимальной яркости

Можно узнать, сколько делается попыток? По статистике, доля a=0,25 всех чисел должн быть отброшена и сгенерирована заново. Вероятность того, что за n попыток не будет выбрано «правильное» число, равна a n .
n=1 0,25 n=2 0,0625 n=3 0,015625 n=4 0,003906

Доля аномально низких уровней яркости составляет 13/3600=0,0036 , что хорошо совпадает с вариантом n=4 . Таким образом, MAX_ATTEMPTS==4 .

Обратите внимание, что более простым решением было бы просто использовать значение из предыдущего кадра, если встретилось недопустимое число. Этот вариант можно было бы исключить, исходя из автокорреляции (см. ниже). Наиболее же простое, вероятно, решение - изменить схему ШИМ - не было здесь использовано.

Последний кусочек головоломки - это сам генератор случайных чисел. Типичным способом генерации случайных последовательностей в цифровых схемах является применение сдвиговых регистров с линейной обратной связью . Такой регистр выдает псевдослучайную битовую последовательность, которая повторится не позже, чем через 2 x -1 тактов, где x - разрядность регистра. Одной из особенностей таких последовательностей (и хороших псевдослучайных последовательностей в целом) является то, что их автокорреляционная функция равна единице только в точке 0 и в координатах, кратных длине последовательности. Во всех остальных интервалах она нулевая.


Я рассчитал автокорреляцию всей последовательности значений. Самоподобия не было найдено вплоть до 3500 кадров (на графике выше показано только 1200), что означает уникальность мерцания на протяжении по меньшей мере 4 минут. Неясно, наблюдалось ли дальнейшее повторение последовательности, или логический анализатор автора просто не позволял записывать дольше - прим. перев. Поскольку на каждый кадр нужно как минимум 5 бит случайных данных (а учитывая механизм отбрасывания нежелательных чисел - еще больше), псевдослучайная последовательность имеет длину по меньшей мере 17500 бит. Для этого потребуется регистр разрядности не менее 17, либо настоящий аппаратный генератор случайных чисел. В любом случае, интересно, как много внимания при разработке уделили тому, чтобы картина мерцания не повторялась.

В заключение ответим на вопросы, заданные в начале статьи. Мерцающий светодиод оказался гораздо сложнее, чем я ожидал (также я не ожидал потратить на него 4 часа). Многие микроконтроллерные реализации свечей просто подают биты с генератора псевдослучайных чисел на ШИМ-выход. Покупной светодиод использует более хитрый алгоритм изменения яркости. Безусловно, определенное внимание было уделено разработке алгоритма, и при этом использован кристалл почти минимально возможной площади. Доля цента потрачена не зря.

Каков же лучший алгоритм мерцания? Можно ли улучшить этот?

Дополнение: Я наконец нашел время написать эмулятор. Написанная на ANSI-C программа, эмулирующая поведение этого светодиода,

разработчик 80-го уровня 17 июля 2015 в 11:33

Мигаем светодиодами на AVR без Arduino

  • DIY или Сделай сам *

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

Возникла потребность в устройстве генерирующем псевдослучайные числа. Почему не случайные а псевдослучайные, так это потому, что невозможно генерировать случайные числа программно: когда-нибудь цикл повторится, к примеру, после очередного включения устройства. Чтобы генерировать случайные числа нужно задействовать внешнее воздействие, вариантов много, давайте обсудим в комментариях. Это было бы сложнее, поэтому вернемся к псевдослучайной генерации. Также в качестве индикаторов чисел будут сетодиоды, ибо так легче.

После длительного гугления, чтения статей, форумов, изучая даташиты и не найдя готового решения решил делать сам. Как мигать светодиодом есть везде, а как мигать случайно - нет. Неужели никто не делал гирлянду? Надеюсь моя инструкция будет интересна начинающему.

Первым делом чертим схему. Схема не моя, свою потерял, поэтому исходника для протеус не будет.

Для тек кто не знает что это за программа, очень советую, очень удобно наблюдать как все работает без пайки и прошивки контроллера. Микроконтроллер фирмы Atmel Atmega8. Почему именно атмел, предлагаю обсудить в комментариях.

Собственно сам код:

#include //Включаем библиотеку для работы с микроконтроллером ATMega8 #include //Включаем библиотеку для организации задержек #include //Включаем библиотеку для генерации псевдослучайных чисел (rand) void main(void) //Обязательный заголовок (тело) { char i; //Объявляем переменную (i) PORTD=0x00; //Выставляем все выходы порта D на 0, то есть, выключаем весь порт D DDRD=0xFF; //Делаем порт D, как выход, чтобы на выходах порта было напряжение 5В PORTC=0x00; //Выставляем все выходы порта C на 0, то есть, выключаем весь порт C DDRC=0xFF; //Делаем порт C, как выход, чтобы на выходах порта было напряжение 5В PORTB=0x00; //Выставляем все выходы порта B на 0, то есть, выключаем весь порт B DDRB=0xFF; //Делаем порт B, как выход, чтобы на выходах порта было напряжение 5В while (1) //Добавляем бессконечный цикл, код ниже выполняется в цикле { i = rand() % 22 + 1; /*Присваеваем переменной функцию, которая принимает значения от 0 до 32767. (В нашем случае делим по модулю)*/ delay_ms(5); //Исполюзуем задержку 5мс if (i==1){PORTD.0=1;} else PORTD.0=0; //Если переменная (i) равна (1) то 0-вой бит порта (D) равен (1), if (i==2){PORTD.1=1;} else PORTD.1=0; // если иначе, то 0-лю if (i==3){PORTD.2=1;} else PORTD.2=0; //Во всех остальных ниже условиях по аналогии if (i==4){PORTD.3=1;} else PORTD.3=0; if (i==5){PORTD.4=1;} else PORTD.4=0; if (i==6){PORTD.5=1;} else PORTD.5=0; if (i==7){PORTD.6=1;} else PORTD.6=0; if (i==8){PORTD.7=1;} else PORTD.7=0; if (i==9){PORTC.0=1;} else PORTC.0=0; if (i==10){PORTC.1=1;} else PORTC.1=0; if (i==11){PORTC.2=1;} else PORTC.2=0; if (i==12){PORTC.3=1;} else PORTC.3=0; if (i==13){PORTC.4=1;} else PORTC.4=0; if (i==14){PORTC.5=1;} else PORTC.5=0; if (i==15){PORTB.0=1;} else PORTB.0=0; if (i==16){PORTB.1=1;} else PORTB.1=0; if (i==17){PORTB.2=1;} else PORTB.2=0; if (i==18){PORTB.3=1;} else PORTB.3=0; if (i==19){PORTB.4=1;} else PORTB.4=0; if (i==20){PORTB.5=1;} else PORTB.5=0; if (i==21){PORTB.6=1;} else PORTB.6=0; if (i==22){PORTB.7=1;} else PORTB.7=0; }; }

Код писал 2 дня, пока понял что к чему. Опишу кратко. Подключаем необходимые библиотеки, в цикле с помощью функции rand() генерируем числа, условия открывают закрывают порты в зависимости от значения переменной «i». А как бы сделали вы? Можно ли сократить код?

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

После необходимо прошить сам микроконтроллер. Тут такая же ситуация. Существует всеми хвалимая программа AVRDUDE, но мне понравилась KhazamaAVRProgrammer. В качестве программатора выступал обычный USBASP:

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

Печатную плату в формате lay можете скачать


Мигающий светодиод проект на AVR


Схема мигающего светодиода проста, это типовая обвязка микроконтроллера AVR Atmega8 (смотри ) + резистор со светодиодом подключенные к выводу 14.

Надеюсь что с установкой и скачкой утилиты вопросов не возникает. Поэтому после инсталляции и перезагрузки ПК запускаем программу и создаем новый проект. Для этого нажимаем в меню File->New. Появится окно "Createe New File" (Создать новый файл). В нем выбираем File Type (Тип файла) - Project (проект) и нажимаем Ok. Появляется новое окно "Вы хотите создать новый проект и использовать генератор кода?" Отвечаете Да (Yes). В окне генератора кода мы выбираем что будет проинициализировано нашим микроконтроллером перед стартом основной программы. Начнем с вкладки Chip , в ней выбираем наш МК: Atmega 8 с частотой 4 МГЦ.

Переходим в следующую вкладку Ports . Здесь в Port B нулевой бит переключаем с In на Out. Значение по умолчанию на выходе оставляем нулевым. Это значит что при запуске МК на порту B в нулевом разряде будет логический ноль. Далее сохраняем наш проект жесткий диск, например в C:/my_cvavr/project_led.

Для генерации стартового кода жмем на иконку "шестеренка" (немного правее иконки сохранить) и дважды под тем же именем сохраняем проект. Давайте теперь рассмотрим отдельные моменты полученного кода.


Строка: include mega8.h в ней мы говорим компилятору о том, что требуется подключить файл с описаниями всех регистров ATmega8

Строка: PORTB=0x00; по умолчанию установлен логический ноль на выходе. Правда этим выражением выводится нули в весь порт. А можно чуть по проще PORTB.0=0x00;

Строка: DDRB=0x01 ; Вспоминаем статью " ". Так как цифра 0x01 в hex равна 0b00000001 и bin. переведя это выражение из шестнадцатеричной системы в двоичную, мы поймем, что в нулевой разряд регистра направления DDRB записали 1, т.е будем выводить данные через нулевой разряд порта В.

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

Так как светодиодом мы управляем через нулевой разряд порта "В", то пишем:

PORTB.0 = 0x01;
PORTB.0 = 0x00;

Это самый простейший способ, в котором мы сначала записываем в нулевой разряд порта, о чем подсказывает точка с нулем после порта, логическую единицу, а затем ноль. По идеи светодиод должен сначала включится, а потом потухнет и так в бесконечном цикле. Но к сожалению или счастью, все не так просто, ведь в данном случае светодиод будет гореть постоянно, т.к частота кварца 4 МГц, т.е 4 миллиона раз за секунду светодиод мигнет, а вот человеческий глаз, без дополнительных плагинов не способен уследить за этим

Что же нам делать? Как вариант, можно вставить паузы длинной в пол секунды или использовать аппаратный таймер с прерыванием. Но раз уж мы мы работаем в утилите CodeVisionAVR, а в ней есть отличная библиотека полезных функций, в которой можно выбрать паузу delay_ms(int x) или delay_us(int x) . В первом случае будет пауза длинной х миллисекунд, а в другом х микросекунд. Но чтоб ей пользоваться придется вернуться на самый верх кода и после строки #include допишем под ней #include , т.е подключим библиотеку и можем пользоваться функциями пауз. Допишем наш код.

PORTB.0 = 0x01;
delay_ms(500);
PORTB.0 = 0x00;
delay_ms(500);

Для сборки проекта. В меню нажимаем Project->Build All, После сборки мы увидим окно в котором говорится, что все сделано без ошибок и нет различных предупреждений. Две строки: No errors и No warnings.

Пишем первую программу!

Большинство начинают с мигания светодиодов, и мы не исключение. Если микроконтроллер, даже самый быстрый, не “общается” с внешним миром, ценность его сводится к нулю. Нам нужно чтобы микроконтроллер принял информацию, обработал по заданному алгоритму и выдал результат в понятной для нас форме.

Алгоритм , (от имени персидского математика аль-Хорезми) - точный набор инструкций, описывающих порядок действий исполнителя для достижения результата решения задачи за определенное время.
Чтобы правильно писать программы нужно понять, как работает микроконтроллер, чем мы и будем заниматься, а пока составим первую программу на ассемблере.

Вообще, написать программу можно в любом текстовом редакторе, так же как вы бы написали письмо другу, например. После этого, текст надо скомпилировать (иногда говорят - ассемблировать) т.е. перевести в форму, понятную процессору. Раньше, расширение текстового файла.txt переименовывали в.asm и обрабатывали специальной программой, называемой компилятором. Суть работы компилятора в переводе письменных символов понятных для человека в машинный код (в код нулей и единиц) и создание нового файла с расширением.hex

Что делать с этим.hex файлом? А он нужен для программатора, чтобы записать код программы в ПЗУ (постоянное запоминающее устройство) микроконтроллера. Мы вместо программатора будем использовать программу Proteus , которая модулирует реальную работающую схему.
В AVR Studio 5 редактор, компилятор, отладчик и программатор все в одном флаконе!

Директива – это предписание редактору, с которым мы будем работать. В большинстве своем название директивы и ее функция в разных редакторах совпадают. Например, если сравнить редактор MPLAB IDE для микроконтроллеров PIC, то разницы практически нет!
А вот команды отличаются. Список команд формируется производителем и в какой-то степени зависит от технологии производства. Даже у одного производителя в разных семействах может быть разный список команд по мере изменения их структуры.
Команда – это единичная функция, с помощью которой мы можем управлять микроконтроллером.
Программа - это последовательность команд, соответствующая определенному алгоритму (составленная нами).
Любая программа начинается с “шапки”, где прописывается основные функции программы, ее автор, название контроллера, который будет использоваться, тактовая частота и другие данные. “Шапка” - это “правило хорошего тона” в программировании.
Обычно в “шапке” прописывается файл инициализации.includeххххdef.inc. директивы.device, .list, .nolist, и другие.
В AVR Studio 5 эти директивы прописаны по умолчанию. В предыдущей версии AVR Studio 4 эти директивы нужно было прописывать, поэтому я их оставил в виде комментариев.
Комментарии пишутся произвольно, как вам нравиться и главное, чтобы они для вас оставались понятными. Нередко, из-за неполных комментариев, через некоторый промежуток времени сам автор не может разобраться в собственной программе. Перед комментариями ставиться знак (;) .
Я ввел “шапку” предложенную Джоном Мортоном…

Редактор AVR Studio 5 – понимает написанные, директивы и команды выделяя их в синий цвет, числовые данные остаются черными, непонятные выражения выделяет в красный, комментарии в зеленый.

Прежде чем начать, что-то писать рассмотрим директивы ассемблера микроконтроллеров AVR.
Перед каждой директивой ставиться точка:
Директива Описание.BYTE Резервировать байты в ОЗУ.CSEG Сегмент программы.DB Определить байт – константу во Flash-памяти или EEPROM .DEF Назначить регистру символическое имя.DEVICE Определяет устройство, для которого компилируется программа.DSEG Сегмент данных.DW Определяет слово во Flash-памяти или EEPROM .ENDM Конец макроса.ENDMACRO Конец макроса.EQU Установить постоянное выражение.ESEG Сегмент EEPROM .EXIT Выход из файла.INCLUDE Вложить другой файл.LIST Включить генерацию листинга.LISTMAC Включить разворачивание макросов в листинге.MACRO Начало макроса.NOLIST Выключить генерацию листинга.ORG Установить положение в сегменте.SET Установить для переменной эквивалентное выражение

Полное описание команд и директив ассемблера в русском переводе Руслана Шимкевича можно посмотреть тут:
🕗 24/09/11 ⚖️ 397,28 Kb ⇣ 244 Здравствуй, читатель! Меня зовут Игорь, мне 45, я сибиряк и заядлый электронщик-любитель. Я придумал, создал и содержу этот замечательный сайт с 2006 года.
Уже более 10 лет наш журнал существует только на мои средства.

Хорош! Халява кончилась. Хочешь файлы и полезные статьи - помоги мне!

--
Спасибо за внимание!

Мы еще не раз вернемся к директивам ассемблера, а сейчас попробуем написать небольшой текст программы, где будем включать светодиоды.
Для удобства выберем микроконтроллер ATtiny2313A . Если кто-то пойдет дальше и будет экспериментировать в “железе”, этот контроллер один из самых доступных, очень часто применяется в различных конструкциях, которые можно найти в бескрайних просторах сети.

--
Спасибо за внимание!
Игорь Котов, главный редактор журнала «Датагор»


Нужно лишь распаковать и стартовать его (при условии, что Proteus уже установлен).
Должна появиться вот такая картинка:

Запустим AVR Studio 5 , и в редакторе напишем небольшую программу с подробными комментариями:
.def temp=r16 ; директива.def назначает регистру r16 имя temp ;==================================================== ; Начало программы.cseg ; директива.cseg определяет начало сегмента, где будет расположен; основной код программы. В AVR Studio 5 это директива не; обязательна.org 0 ; начало первой строки программы rjmp Start ; относительный переход к метке Start (в PIC соответствует; команде goto) ; ==================================================== Start: ser temp; устанавливает все биты регистра temp в 1 out DDRB,temp; переводит все биты out DDRD,temp; порта B и D на вывод clr temp; обнуляет регистр temp (устанавливает все биты регистра temp в 0) out PortB,temp; отключает подтягивающие резисторы out PortD,temp; портов B и D Cicle: ldi temp,0b11001100; включает светодиоды out PortB, temp; порта B rjmp Cicle; Возвращаемся к метке Cicle, зацикливаемся

Скомпилируем ее, кликнув по F7
В окошке Output появятся информация о проведенной компиляции, в конце должна быть надпись Build succeeded, которая подтверждает удачную сборку.hex файла.


Этот файл по умолчанию размещен в Моих документах, в проекте AVR Studio 5.

Переходим в Proteus , кликаем на рисунок контроллера и вводим путь, где находиться.hex файл:




Запускаем эмуляцию программы.
После нажатия кнопки Старт видим результат!



Чтобы остановить эмуляцию – кликаем Стоп.
Если прошить микроконтроллер программатором и собрать схему, то результат будет таким-же.

Попробуем разобраться, с программой:

Строка:
.def temp=r16 ; директива.def назначает регистру r16 имя temp
Для удобства мы назначили регистру r16 имя temp, это значит что в любом месте программы, при написании слова temp программа будет обращаться к регистру r16.
Что это за регистр – r16?
Он относится к регистрам общего назначения, которые обозначаются как r0….r31, т.е их всего 32 по 8 бит. Вторая половина регистров общего назначения r16…r31 выполняют функцию временного хранения информации (как аккумуляторы, могут принимать и могут отдавать информацию, для сравнения - у PIC контроллеров всего один аккумулятор W). Последние 6 регистров общего назначения условно объединены в три 16-битных:

Обратите внимание, что старший байт пишется раньше, младший позже.

r27:r26 называется регистром X,
r29:r28 называется регистром Y,
r31:r30 называется регистром Z
Программа будет так же работать если слово temp будет присвоено любому другому регистру общего назначения от r16 до r31 например.def temp=r20. После компиляции (клавиша F7 в AVR Studio 5), разницы в работе программы никакой нет.
(Можете попробовать, теперь вы знаете, как это сделать!)

Строка:
.cseg ; директива.cseg определяет начало сегмента, где будет расположен основной код программы
В AVR Studio 5 это директива прописана по умолчанию.
В микроконтроллерах AVR выделяют разные области памяти, для хранения программного кода, данных в постоянной памяти или EEPROM, для обозначения этой области существуют директории:
.cseg - Программный сегмент
.dseg – Сегмент данных
.eseg – сегмент EEPROM

Строка:
.org 0 ; начало первой строки программы
Программа начинается со строки указанной директивой.org, и при завершении будет возвращаться к ней.

Строка:
rjmp Start ; относительный переход к метке Start (в PIC соответствует команде goto)
Это команда относительного перехода к метке Start.
Программа выполняется последовательно от верхней стоки к нижней. Если требуется перейти в другую область программы то используется команда rjmp

Строки:
ser temp ; устанавливает все биты регистра temp в 1 clr temp ; обнуляет регистр temp (устанавливает все биты регистра temp в 0)
Команда ser выполняется с регистрами r16…r31, а команда clr может выполнятся ко всем регистрам, в том числе и регистрам ввода-вывода (регистрам специального назначения). Назначение этих регистров мы рассмотрим позже.

Строка:
ldi temp,0b11001100
Команда ldi записывет в регистр temp двоичное число 11001100 (не будет ошибкой если вместо 0b11001100 написать 204 или CCh, в одном случае в десятичной форме в другом в шестнадцатеричной)

Строка:
out DDRB,temp
Команда out выводит значение регистра temp в регистр порта DDRB.

Что такое порт и как он работает?

Если упростить до минимума, то порт можно представить как ножку-вывод микроконтроллера, на который в режиме вывода можно произвольно подать напряжение или отключить, а в режиме ввода определить, есть ли напряжение, поданное извне или нет.
Есть три режима работы порта: это вывод, ввод и отключенное состояние.
Управляют портами регистры PinX, PortX, DDRX.
Х – означает порт, которым управляют эти регистры.
Регистр DDRX управляет режимами ввода-вывода, как реле – включили (записали 1) – подключился на линию вывода, отключили (записали 0) – переключился на линию ввода (по умолчанию).

Чтобы вывести данные в порт Х, нужно регистр DDRX переключить в режим вывода (прописать 1) а данные переслать в регистр PortX.
Считать значение порта Х можно, если регистр DDRX переключить в режим ввода (прописать 0), из регистра PinX. Чтобы подключить подтягивающие резисторы в режиме ввода, надо отправить данные в PortX.
Подтягивающие резисторы избавляют нас от необходимости подключать внешние резисторы на положительный провод и с помощью одной команды сами подают логическую единицу на вход.

Читательское голосование

Статью одобрили 23 читателя.

Для участия в голосовании зарегистрируйтесь и войдите на сайт с вашими логином и паролем.

Добавлено: 28.06.2017 в 13:00

В этом примере мы напишем нашу первую программу на Си для микроконтроллера ATtiny13. Предполагается, что у нас уже подготовлено к работе всё необходимое: среда разработки, компилятор и т.д. Подопытным у меня будет самодельная отладочная плата , соответственно весь код буду приводить применительно к ней.
В качестве тестовой программы напишем классический, простейший пример "blink", который будет мигать светодиодом с определённой частотой.

Итак, создаём новый проект и приступаем. Приведу сразу полный код программы, а затем поясню всё более подробно:

/* * tiny13_board_blink * Демо-прошивка отладочной платы на ATtiny13 * с целью проверки работоспособности МК. * Мигаем светодиодом. */ #define F_CPU 1200000UL // Указываем тактовую частоту МК #define LED PB2 // Используем светодиод, подключенный к PB2 (7 пин) #include // Подключаем определения ввода/вывода #include // Подключаем библиотеку функций задержки int main(void) { // Светодиод DDRB |= (1<

В самом начале задаём значения констант и подключаем заголовочные файлы и библиотеки.
Файл avr/io.h подключает определения ввода/вывода для конкретного типа микроконтроллера (тип МК указывается в виде опции для компилятора).
Библиотеку util/delay.h подключаем для использования функций задержки, в нашем случае: _delay_ms() . Для работы функций задержки мы должны указать тактовую частоту процессора. Поэтому ДО подключения util/delay.h определяем константу F_CPU (в данном случае - 1,2МГц).

Затем у нас идёт основная функция main - это, собственно, тело нашей программы. Здесь мы должны, сначала, описать все действия, которые будут происходить при старте микроконтроллера, а затем, в бесконечном цикле запустить выполнение основной программы:

while (1) { ... }

Для начала, мы должны сконфигурировать порт ввода/вывода. В МК AVR старших моделей портов в/в может быть несколько (A, B, C, D). К каждому порту может быть подключено до восьми ножек. Каждая из ножек может быть настроена как на вход, так и на выход. ATtiny13 имеет только один порт (B), к которому подключены шесть ножек (PB0-PB5, см. datasheet). По умолчанию все ножки настроены на вход, а чтобы управлять светодиодом, мы должны использовать соответствующую ножку как выход. В микроконтроллерах AVR вся аппаратная часть настраивается посредством восьмибитных регистров. Направление (вход-выход) устанавливается битами регистров DDRx (где x - буква порта, в нашем случае B). Значение бита "0" - соответствует входу, "1" - выходу. Таким образом, чтобы использовать ножку PB2, как выход, мы должны установить второй бит регистра DDRB в единицу:

DDRB |= (1<

Для управления состоянием выхода предназначены регистры PORTx. Например, чтобы выключить светодиод, подключенный к ножке PB2 (подать низкий уровень сигнала), мы должны записать ноль во второй бит регистра PORTB :

PORTB &= ~(1<

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

PORTB |= (1<

Теперь, когда порт в/в сконфигурирован, мы запускаем основной цикл, в котором будем инвертировать состояние выхода PB2 (чередовать высокий и низкий уровень сигнала) с задержкой 500мс. Таким образом, светодиод у нас будет мигать с частотой 1 раз в секунду.

THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама