Конфигурирование портов в Bascom-AVR
Любой микроконтроллер умеет общаться с внешней периферией. Для этого у них есть порты общего назначения, которые могут работать в качестве входов (для подключения кнопок, для приема данных, для обработки внешних сигналов и т.д.), а так же в качестве выходов (для вывода данных, для подключения светодиодов, индикаторов, сервомашинок и других элементов которыми можно управлять).
Для того чтобы использовать любой порт микроконтроллера, его сперва необходимо сконфигурировать в качестве входа или выхода. На примере самого распространенного микроконтроллера AVR давайте сконфигурируем две его ножки в качестве выхода - PortB.0 (PB0) и входа PortB.1 (PB1)
В Bascom-AVR конфигурация портов выглядит следующим образом:
Config PortB.0 = Output
Config PortB.1 = Input
Config PortB.1 = Input
здесь мы отдельно указываем для каждого вывода микроконтроллера как он должен работать - как вход (Input) или как выход (Output).
Такой способ удобен, когда нужно сконфигурировать небольшое количество ножек.
Бывают случаи когда весь порт должен быть сконфигурирован как вход или как выход, тогда пишется та же команда что и выше, но без указания номера порта:
Config PortB = Output 'весь порт B сконфигурирован как выход
Так же нередки случаи когда используется весь порт, но не в одном каком-то режиме, а некоторые ножки должны работать как выход, а некоторые как вход.
К примеру, давайте сконфигурируем целиком порт микроконтроллера следующим образом:
PortB.0, PortB.1, PortB.3, PortB.5, PortB.6, PortB.7 на выход
PortB.2 и PortB.4 на вход.
Из рассмотренного выше примера, можно записать вот так:
Config Portb.0 = Output
Config Portb.1 = Output
Config Portb.2 = Input
Config Portb.3 = Output
Config Portb.4 = Input
Config Portb.5 = Output
Config Portb.6 = Output
Config Portb.7 = Output
Config Portb.1 = Output
Config Portb.2 = Input
Config Portb.3 = Output
Config Portb.4 = Input
Config Portb.5 = Output
Config Portb.6 = Output
Config Portb.7 = Output
это все можно настроить через специальный регистр DDR, настройка займет всего одну строчку кода:
Ок, но не будем останавливаться на простом конфигурировании портов. Ведь все это проделывается лишь с целью дальнейшего использования настроенных портов в своих проектов. Да и гораздо интересней вживую наблюдать за результатом своих трудов;)
Давайте рассмотрим самый простой пример: к микроконтроллеру Attiny2313 подключен светодиод и кнопка. Чтобы далеко не ходить, давайте сконфигурируем порты как в первом примере: т.е. PortB.0 - выход, сюда подключим светодиод; и PortB.1 - вход, сюда подключим кнопку. Получаем вот такую схему:
DDRB = 11101011 '2 и 4 ножки порта B сконфигурированы на вход, остальные - на выход
Ок, но не будем останавливаться на простом конфигурировании портов. Ведь все это проделывается лишь с целью дальнейшего использования настроенных портов в своих проектов. Да и гораздо интересней вживую наблюдать за результатом своих трудов;)
Давайте рассмотрим самый простой пример: к микроконтроллеру Attiny2313 подключен светодиод и кнопка. Чтобы далеко не ходить, давайте сконфигурируем порты как в первом примере: т.е. PortB.0 - выход, сюда подключим светодиод; и PortB.1 - вход, сюда подключим кнопку. Получаем вот такую схему:
Светодиод будет гореть если на анод (т.е. на PortB.0), будет подана логическая единица. Сразу после конфигурирования в качестве выхода, на ножке устанавливается низкий уровень и светодиод гореть не будет.
Кнопка подключена таким образом, что при нажатии на входе порта установится логический 0 (говорят, что прижимаем порт к земле).
Теперь нужно пояснить для чего нужен резистор R1. Дело в том что после конфигурирования порта в качестве входа, на этом входе устанавливается так называемое высокоимпедансное состояние - состояние при котором на входе нет какого-либо четкого уровня. И в зависимости от внешних помех на входе может быть как логический ноль, так и логическая единица. Это ведет к непредсказуемой логике работы программы. В нашем случае активным состоянием выбран логический ноль, это состояние на входе будет означать что кнопка нажата. Так вот чтобы избежать помех и четко зафиксировать высокий уровень на входе порта когда кнопка еще не нажата, используется подтягивающий резистор в несколько килоом.
Теперь приступим к написанию программы и придумаем алгоритм. Для начала напишем очень простую программу,которая будет постоянно опрашивать вход и если микроконтроллер увидит что кто-то нажал кнопку, зажгет светодиод.
$regfile = "2313def.dat" 'указываем компилятору что работать будем с Attiny2313
$crystal = 1000000 'частота работы микроконтроллера 1МГц
Config Portb.0 = Output 'устанавливаем PortB.0 в качестве выхода
Config Portb.1 = Input 'устанавливаем PortB.1 в качестве входа
Do 'начало главного цикла
If Pinb.1 = 0 Then 'условие: если на входе обнаружен низкий уровень
Portb.0 = 1 'устанавливаем на выходе высокий уровень
Else 'иначе, если это условие не выполняется
Portb.0 = 0 'на выходе будет низкий уровень
End If
Loop 'повторяем весь цикл сначала
End 'конец программы
$crystal = 1000000 'частота работы микроконтроллера 1МГц
Config Portb.0 = Output 'устанавливаем PortB.0 в качестве выхода
Config Portb.1 = Input 'устанавливаем PortB.1 в качестве входа
Do 'начало главного цикла
If Pinb.1 = 0 Then 'условие: если на входе обнаружен низкий уровень
Portb.0 = 1 'устанавливаем на выходе высокий уровень
Else 'иначе, если это условие не выполняется
Portb.0 = 0 'на выходе будет низкий уровень
End If
Loop 'повторяем весь цикл сначала
End 'конец программы
Заметьте, что считывание состояния на входе происходит по команде Pin, а установка нужного уровня на выходе - по команде Port.
После компиляции программы (нажимаем F7), полученный *.hex файл прошиваем в микроконтроллер. Программатор, с помощью которого происходит прошивка программатора, можно собрать самостоятельно, схем в интернете очень много. Я лично остановил свой выбор на программаторе USBasp.
Также Bascom-AVR позволяет давать каждому порту свое индивидуальное имя, это сделано для удобства написания программ, так как проще ориентироваться в понятных для себя названиях, чем с номерами портов.
$regfile = "2313def.dat" 'указываем компилятору что работать будем с Attiny2313
$crystal = 1000000 'частота работы микроконтроллера 1МГц
Config Portb.0 = Output 'устанавливаем PortB.0 в качестве выхода
Config Portb.1 = Input 'устанавливаем PortB.1 в качестве входа
Led Alias Portb.0 'даем имя порту выхода
Button Alias Pinb.1 'даем имя порту входа
Do 'начало главного цикла
If Button = 0 Then 'условие: если на входе обнаружен низкий уровень
Led = 1 'устанавливаем на выходе высокий уровень
Else 'иначе, если это условие не выполняется
Led = 0 'на выходе будет низкий уровень
End If
Loop 'повторяем весь цикл сначала
End 'конец программы
$crystal = 1000000 'частота работы микроконтроллера 1МГц
Config Portb.0 = Output 'устанавливаем PortB.0 в качестве выхода
Config Portb.1 = Input 'устанавливаем PortB.1 в качестве входа
Led Alias Portb.0 'даем имя порту выхода
Button Alias Pinb.1 'даем имя порту входа
Do 'начало главного цикла
If Button = 0 Then 'условие: если на входе обнаружен низкий уровень
Led = 1 'устанавливаем на выходе высокий уровень
Else 'иначе, если это условие не выполняется
Led = 0 'на выходе будет низкий уровень
End If
Loop 'повторяем весь цикл сначала
End 'конец программы
Так программа становится более читаема. Но самое главное, что если нужно переназначить какую-нибудь ножку, это достаточно сделать в одном месте, там где мы ее сконфигурировали.