Мигание светодиода на atmega 328. Программирование микроконтроллеров AVR. Что такое ” L” светодиод

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

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

Также после запуска настроим в качестве отладчика симулятор. Также, чтобы нам не мучиться с кодом и не вводить его заново, мы его скопируем с прошлого занятия, открыв в проекте с прошлого занятия файл main.c в любом редакторе и скопировав весь код в буфер обмена. Удалим весь код из файла main.c в новом проекте и вставим из буфера обмена код.

Теперь начнем исправления. То есть мы создадим новый код, а старый у нас будет нетронутым в прошлом проекте. Порт D мы полностью весь установим в 0, изменив 1 на 0 в следующей строке

PORTD = 0b00000000;

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

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

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

Логические операции мы будем производить над восьмибитовыми числами или байтами, которые мы представим в виде прямоугольников, состоящих из восьми ячеек. Первые три операции будут выполняться над двумя числами. Возьмём, к примеру вот такие:

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

Первая — это операция "И ", обозначаемая в языке C/C++ знаком "& ". Любой бит в результате будет установлен в единицу только в том случае, если оба соответствующих ему бита в операндах будут единицами . В любом другом случае мы получаем ноль .

Поэтому результат у нас будет следующий

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

Сделующая логическая операция — это операция "ИЛИ ", обозначаемая вертикальной чертой "| ". В результате данной операции мы получим единицу , если хотя бы один бит в сравниваемых одноименных битах будет установлен в единицу . Таким образом, ноль мы получим только тогда, когда в обеих сравниваемых битах будет ноль .

Поэтому здесь будет уже вот такой результат

Третий вид операции — операция "Исключающее ИЛИ ". Эта операция обозначается знаком "^ ". Здесь шансы у бита стать нулём или единицей уравниваются. Единицей результирующий бит станет тогда, когда сравниваемые биты обязательно будут разными — один будет нулём , другой — единицей . А нулём будет результирующий бит тогда, когда сравниваемые биты будут одинаковыми.

Итак, получим следующий результат

А четвертая операция — операция "НЕ ", обозначаемая знаком тильда — "~ ", проделывается над одним байтом. В результате данной операции все биты меняются обратный. То есть ноль становится единицей , а единица нулём . Данную операцию ещё называют операцией инвертирования .

Вот такой вот получим результат

Теперь вернёмся к коду. Напишем следующую очень непонятную на первый взгляд команду

while (1)

PORTD |=(1<<(PORTD0 ));

Первый непонятный оператор в данной команде — это сдвоенный оператор "|= ". Такого рода операторов существует несколько. В данном случае сначала результат, который получится в правой части, сразу не присваивается переменной. которая находится в правой части, а складывается логически по "ИЛИ " со значением, хранящемся до этого в перменной, которая находится справа. Затем уже результат, полученный после применения данной логической операции, присваивается переменной, находящейся в правой части. Также существуют подобные операции типа "+= и "-= ", которыми мы в дальнейшем будем очень часто пользоваться.

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

Битовые сдвиги бывают двух видов:

"<< " — сдвиг влево,

">> " — сдвиг враво.

Давайте остановимся на них немного поподробнее.

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

Давайте проделаем данные операции над определённым байтом

Ну, я думаю, со сдвигом всё ясно. Давайте проделаем данную операцию над нашим примером в коде

Единичка, стоящая слева — это число, над которым проводится операция, а не число, на которое мы сдвигаем байт побитно, как очень многие путают. Запомните это накрепко! То есть в нашем случае — это единица или в двоичном выражении 0b00000001 . А PORTD0 — это константа, которая определена в макросе в файле io.h . Вот разновидности данных констант

#define PORTD7 7

#define PORTD6 6

#define PORTD5 5

#define PORTD4 4

#define PORTD3 3

#define PORTD2 2

#define PORTD1 1

#define PORTD0 0

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

Дальше мы делаем операцию "ИЛИ" между значением, находящимся в переменной PORTD и данным результатом, равным единице. Так как у нас в порте D в данный момент находится ноль на всех ножках, то мы только установим единицу на нулевой ножке, так как 0b00000000 и 0b00000001 в результате данной операции дадут на 0b00000001 . Но если бы в регистре порта D находилось бы какое-нибудь другое число, то мы также бы установили бы единицу в нулевом бите, а остальные биты бы не тронулись. То есть мы в результате команды получили и лояльную к остальным лапкам операцию, и в то же время эта операция у нас имеет очень наглядный и читабельный вид.

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

Delay_ms (число в милисекундах )

Delay_us (число в микросекундах )

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

#include

#include

Мы воспользуемся первой командой и применим задержку на 500 милисекунд

PORTD |=(1<<(PORTD0 ));

_delay_ms (500);

Теперь можно погасить светодиод. Делается это с помощью следующей команды

Delay_ms (500);

PORTD &=~(1<<(PORTD0 ));

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

Давайте разберём данную команду. Результат справа нам известен — это 0b00000001 , если мы его инвертируем то получим соответственно 0b11111110 . Тепрь его нужно умножить логически на значение в переменной справа. В данный момент там у нас также 0b00000001 . Соответственно получим мы все нули, так как сравниваемые биты в операндах у нас разные. А если бы было какое-то другое чесло в переменной PORTD, то у нас бы сбросился только нулевой бит, остальные бы не тронулись. Поэтому вот такой операцией в будущем мы и будем сбрасывать определенные биты в регистрах и переменных. Также можно сбрасывать сразу несколько битов или устанавливать, но об этом позже, а то и так мы слишком много уже узнали. Осталось нам добавить ещё такую же задержку, чтобы светодиод находился в погасшем состоянии столько же. сколько и в светящемся

PORTD &=~(1<<(PORTD0 ));

_delay_ms (500);

Но это ещё не всё. Чтобы задержка корректно работала, мы обязаны ещё в начале модуля или файла main.c написать макрос, говорящий компилятору о том, с какой частотой работает наш контроллер, иначе он неправлиьно применит задержку, и нам даст предупрежедение. Напишем данный макрос

#define F_CPU 8000000

#include

Соберём проект. У нас ошибок и предупреждений нет

Теперь мы можем посмотреть результат работы сначала в протеусе, затем на живом светодиоде и контроллере.

Чтобы нам заново не создавать схему, мы файл с проектом для проетуса из папки с проектом из прошлого урока скопируем в папку с новым проектом и переименуем в Test02.pdsprj .

Запустим его. Щёлкнем двойным щелчком по изображению контроллера и выберем там другую прошивку, соответствующую новому проекту, а также выставим в свойствах соответствующую частоту, иначе светодиод будет мигать в 8 раз медленнее

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

Затем прошьём настоящий контроллер, и также убедимся, что светодиод мигает и там.

Смотреть ВИДЕОУРОК

Post Views: 11 097


Мигающий светодиод проект на 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.

Добавлено: 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 раз в секунду.

В статье будет рассмотрено подключение светодиодов к микроконтроллеру, работа с портами и написание программы на СИ. Статья, прежде всего, предназначена новичкам, которые только взялись за микроконтроллеры AVR.

Для начала нужно выбрать микроконтроллер. В моем случае это ATmega8535. В данном случае микроконтроллер можно брать любой, так как данная задача легко реализуется под любой МК. Писать программу для микроконтроллера можно на Ассемблере, СИ, Pascal-е и Bascom. Я использовал язык СИ, все эти языки разные.
Конкретную разницу между Си и Паскалем можно увидеть ниже.

//Мигающий светодиод void main() { ddrB = 0b11111111; //задаём порты B на выход portB = 0b11111111; //по умолчанию всё выключено while(1) { portB = ˜portB; //переключаем состояние светодиода на обратное delay_ms(100); //делаем задержку на 100 миллисекунд } }

Program First; begin ddrB:= $FF; //задаём порт B на выход portB:= $FF; //по умолчанию ничего не горит while(1) do begin portB:= not(portB); //переключаем состояние светодиода на обратное delay_ms(100); //делаем небольшую задержку end; end.

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
U1 МК AVR 8-бит

ATmega8535

1 В блокнот
R1-R8 Резистор

220 Ом - 1 кОм

8 В блокнот
R9-R11 Резистор

10 кОм

3 В блокнот
V1-V8 Светодиод 8 В блокнот
Тактовая кнопка 3

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

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

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

Вообще, написать программу можно в любом текстовом редакторе, так же как вы бы написали письмо другу, например. После этого, текст надо скомпилировать (иногда говорят - ассемблировать) т.е. перевести в форму, понятную процессору. Раньше, расширение текстового файла.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 читателя.

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