CUSTOMELECTRONICS.RU
Информационно-учебный блог о разработке электроники
Эл. почта: info@customelectronics.ru

AVR. Управление цифровыми выходами. Начало

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

Подготовка к работе

Как уже говорилось выше, все наши примеры описаны и проверены для наших плат EduBoard и TutorShield.
Плата EduBoard имеет 20 выводов, которые можно использовать как цифровые выходы. Максимальный ток каждого вывода – 20мА. Tutor Shield позволяет к каждому из этих выводов подключить по одному светодиоду.
Умение программировать алгоритмы зажигания светодиодов может понадобится, например, для создания оригинальных подсветок в декоративных целях. В данном случае светодиод применяется лишь как пример исполнительного устройства. Микроконтроллер может управлять транзистором, оптопарой, реле и т.д.
Для выполнения первой части работы вам достаточно платы EduBoard и светодиода на ней, который уже подключен к 13му выводу.

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

Для понимания работы цифрового выхода микроконтроллера разберем его упрощенную эквивалентную схему:

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

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

Для управления выводом используется три регистра — DDR, PORT и PIN.
Регистр DDR управляет настройкой вывода на вход или выход. Если записать в него "1", то переключатель замкнется и выход усилителя будет подключен напрямую к выводу. То есть вывод будет настроен на выход и на ноге будет напряжение, соответствующее состоянию регистра PORT. Запись "0" в регистр DDR разомкнет переключатель и переведет вывод в состояние входа. При этом выход усилителя может быть подключен к выводу микроконтроллера через большое сопротивление резистора. Оно служит для подтяжки вывода к определенному логическому уровню.
Реальное состояние вывода можно всегда определить, обратившись к регистру PIN.
Другими словами для настройки вывода на выход, достаточно записать в регистр DDR "1" и в последующем по мере необходимости записывать в регистр PORT "1" или "0", при этом на выводе будет появляться напряжение 5 или 0 вольт, соответственно.
Для настройки на вход нужно записать в регистр DDR "0". После этого достаточно считать состояние регистра PIN и микроконтроллер узнает, какой логический сигнал подан на вход МК.
Рассмотрим настройку вывода на выход на конкретном примере.

Первый пример

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

#include <avr/io.h>
#define F_CPU 16000000UL //16MHz
#include <util/delay.h>

int main(void) {
	DDRB  |= 1<<5;
	PORTB &= ~1<<5;
	while(1) {
		PORTB |= 1<<5;
		_delay_ms(100);
		PORTB &= ~1<<5;
		_delay_ms(100);
	}
}

Скомпилируйте его и загрузите в память МК, воспользовавшись инструкциями из предыдущей статьи. Вы увидите, что 13й светодиод в линейке начнет мигать.
Разберем структуру программы для микроконтроллера:

Компоновка программы для микроконтроллера

Компоновка программы для микроконтроллера

Сначала идет подключение различных библиотек. У нас подключено два. avr/io.h содержит описание различных констант, определения регистров и т.д. Библиотека util/delay.h позволяет создавать задержки в программе. Для работы этой библиотека необходимо определить частоту, что и делается директивой #define F_CPU 16000000UL. Программа всегда выполняется от первой строчки к последней и задать частоту нужно обязательно раньше, чем подключить библиотеку delay.h. F_CPU — часто используемая различными библиотеками константа. Лучше всего объявлять ее значение в самом начале программы.
main — основная программа. Сначала в ней выполняется первичная настройка (и другие действия, которые нужно выполнить только один раз), затем запускается бесконечный цикл в котором выполняется основная программа.
Чтобы продолжить разбор приведенной программы необходимо сделать небольшое отступление.

Обращение к выводам микроконтроллера

Основной документ разработчика встраиваемого ПО это datasheet от производителя. Мы программируем микроконтроллер Atmega8. На самом деле, в нем содержится исчерпывающая информация и чем быстрее вы в нем освоитесь, тем лучше. Для начала нам потребуется ознакомиться с расположением выводов микроконтроллера:

Расположение выводов микроконтроллера Atmega8

Расположение выводов микроконтроллера

Выводы называются в соответствии с битами управляющих регистров. Например, вывод PD3 управляется третьим битом в регистрах PORTD, PIND и DDRD; PB0 — нулевой бит регистров PORTB, PINB и DDRB и т.д.
В Arduino эти названия переименованы в цифровые выводы D0-D13 и аналоговые входы A0-A5. На обратной стороне TutorShield нанесена таблица с соответствием этих выводов Arduino выводам микроконтроллера:

Соответствие выводов

Соответствие выводов

Благодаря этой шпаргалке вам будет проще определить к какому выводу МК подключен элемент.
Снова вернемся к коду. Напомню, что мы пишем программу, которая будет мигать светодиодом, подключенным к выводу PB5 (D13 Arduino).
Для начала нужно выполнить настройку вывода на выход, для чего в пятый бит регистра DDRB нужно записать "1".
Это происходит в первой строчке:

DDRB  |= 1<<5;

Оператор "<<" это сдвиг влево, а запись "1<<5" означает что в двоичном числе единицу необходимо сдвинуть пять раз. Результатом такой операции будет число 0b00100000 (в двоичной системе исчисления). Оператор "|=" производит логическое сложение содержимого регистра DDRB с числом "1<<5". При логическом побитовом сложении единицы с любым числом, результатом будет "1". При сложении любого числа с нулем, получится исходное число.
Все это означает, что после выполнения команды "DDRB |= 1<<5;" в пятом бите регистра DDRB окажется "1", а остальные биты не изменят свое состояние.
То же самое действие можно записать многими способами и программа будет выполняться одинаково. Предложенный формат записи является одним из самых наглядных и часто используемых.
Перейдем к следующей строке:

PORTB &= ~1<<5;

Прежде чем перейти к выполнению основной программы нужно задать начальное состояние вывода. Запишем в пятый бит регистра PORTB "0", чтобы на выводе было напряжение 0В.
Здесь мы сталкиваемся с еще двумя незнакомыми операциями. Оператор "~" означает инверсию, а запись "~1<<5" означает двоичное число 0b11011111, то есть число, обратное число 0b00100000. Это число также перемножается с содержимым регистра PORTB и результат записывается в регистр PORTB.
Битовое умножение на "0" любого числа дает в результате "0". При умножении любого числа на "1" результатом будет исходное число. В итоге, после выполнения команды "PORTB &= ~1<<5;", в пятом бите регистра PORTB будет ноль, а остальные не изменят свое состояние.
На этом мы закончили настройку микроконтроллера и можем запустить основной бесконечный цикл. В нашем примере цикл описан оператором while; и выполняется он пока условие входа в цикл истинно, то есть равно "1". Так как это значение задано изначально, условие будет выполняться всегда и микроконтроллер, пока подано питание, будет бесконечно циклично выполнять содержимое тела цикла.
Наша задача мигать светодиодом пять раз в секунду. Для этого надо на ноге PB5 выставить напряжение логической единицы, подождать 100мс, выставить напряжение логического нуля и подождать еще 100мс. Дальше выполнение программы начнется заново.
Все эти действия так и записаны последовательно друг за другом.

while(1) {
		PORTB |= 1<<5;
		_delay_ms(100);
		PORTB &= ~1<<5;
		_delay_ms(100);
	}

В этой части кода остается пояснить только команду _delay_ms(100);. Это функция, для которой мы подключали библиотеку delay.h. То есть нам не нужно придумывать способ остановки выполнения программы. Достаточно просто вызвать функцию _delay_ms(x) и вместо "x" подставить требуемое значение задержки в миллисекундах. Когда программа дойдет до этого места, то она выполнит остановку. Если этих пауз не выполнять, светодиод будет мигать так быстро, что глазу это не будет видно.

Итоги

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

Мы будем очень рады, если вы поддержите наш ресурс и посетите магазин наших товаров shop.customelectronics.ru.

Метки: , , , , Просмотров: 10392