Порты ввода-вывода микроконтроллера
В этом статье мы напишем первую программу и научимся программировать порты ввода-вывода микроконтроллера.
Наша первая программа будет управлять, по началу, одним из выводов микроконтроллера. Для того чтобы удостоверится в том, что программа работает, к управляемому выводу через токоограничивающий резистор мы подключим светодиод, анод которого соединен с выводом МК, а катод с минусом (общим проводом).
По умолчанию, на всех выводах незапрограммированного микроконтроллера напряжение близкое к нулю, поэтому светодиод не будет светиться. Наша задача состоит в том, чтобы написать программу, с помощью которой на выводе МК появится напряжение +5 В. Это напряжения (точнее буде ток) засветит светодиод.
Порты ввода-вывода микроконтроллера
Микроконтроллер ATmega8 имеет 28 выводов, каждый из них выполняет определенные функции. Светодиод можно подключить к большинству выводов, однако, не ко всем, ведь минимум пара выводов занята под питание. Чтобы четко знать назначение каждого вывода МК воспользуется даташитом. В даташите находим распиновку (обозначение) всех выводов.
Почти каждый вывод может выполнять несколько функций. Сокращения названий функций приводятся в скобках рядом с выводами. В последующих статья мы обязательно их все рассмотрим. Сейчас же нас интересуют некоторые из них.
Для работы микроконтроллера, впрочем, как и любой другой микросхемы, необходимо напряжение. Во избежание ложных срабатываний МК нужно питать только стабильным напряжением от 4,5 В до 5,5 В. Этот диапазон напряжений строго регламентирован и приведен в даташите.
Плюс («+») источника питания подсоединяется в 7-й ножке, обозначенной VCC. Минус («-») – к 8-й или 22-й ножке, которые имеют обозначение GND (GND – сокращенно от ground – «земля»).
Остальные ножки позволяют микроконтроллеру взаимодействовать с внешними устройствами. Они объединены в отдельные группы и называются порты ввода-вывода микроконтроллера. С помощью них можно как подавать сигналы на вход МК, например с различных датчиков, так и выдавать сигналы для управления другими устройствами или для отображения информации на различных индикаторах и дисплеях.
Микроконтроллер ATmega8 имеет три порта ввода-вывода: B, C и D. Порты могут быть полными и неполными. Полный порт состоит из восьми бит и соответственно имеет столько же одноименных выводов. У неполного порта меньше 8 бит, поэтому число выводов такого порта также менее восьми.
У данного МК порты B и D полные. А порт C неполный и имеет семь бит. Еще раз обращаю внимание, что нумерация битов начинается с нуля, например PB0, PB1, PB2…
Не удивляйтесь, что у ATmega8 отсутствует порт A. Другие МК, имеющие большее число выводов, могут содержать как порт A, так и порт E. У микроконтроллеров с меньшим числом выводов может быть только один порт и тот неполный.
Знакомство с Atmel Studio 7
Теперь перейдем к написанию кода программы. Наша первая программа будет устанавливать + 5 В на нулевом бите порта C PC0, т.е. на 23-м выводе микроконтроллера.
Запускаем Atmel Studio.
Сначала необходимо создать проект. Для этого в открывшемся окне кликаем по вкладке New Project.
Также проект можно создать, кликнув по вкладке File. В выпавшем меню следует выбрать New и далее Project. Или нажать комбинацию клавиш Ctrl+Shift+N.
В появившемся окне выбираем язык программирования C/C++ и кликаем по вкладке.
Далее нам нужно задать имя и место на диске для нашего проекта. Назовём наш первый проект именем 1 в строке для ввода Name. Изменить место расположения файла можно кликнув по кнопке Browse напротив строки Location. Если оставить галочку возле Create directory for solution, то в выбранном месте автоматически создастся папка с именем проекта. В данной папке помимо проекта будут созданы и другие вспомогательные файлы, поэтому я рекомендую не убирать галочку.
После того, как имя проекта и его место выбраны, нажимаем кнопку OK. Снова появляется окно. В нем нам нужно выбрать тип микроконтроллера. В нашем случае – это ATmega8. Кликаем по вкладке Device Family. В выпавшем меню выбираем серию микроконтроллеров ATmega.
С помощью прокрутки находим и выделяем микроконтроллер ATmega8 и наживаем кнопку OK.
В открывшемся окне мы видим, что Atmel Studio нам автоматически сформировала заготовку или же шаблон программы.
Рассмотрим все по порядку.
Atmel Studio 7 | Первая программа
Текст, выделенный зеленым цветом – это комментарии. В данном случае приводится имя проекта и автора, а также время и дата создания проекта. Комментарии не являются программным кодом, поэтому они игнорируются компилятором. Комментарии позволяют программисту улучшить читаемость кода, что особенно помогает при поиске ошибок и отладке программы.
Цвет комментариев и других элементов программы можно изменять в настройках Atmel Studio.
/*
* 1.c
*
* Created: 07.08.2017 16:57:59
* Author : ZBL
*/
Комментарии бываю однострочные и многострочные. В данном шаблоне программы применяются многострочные комментарии. Они начинаются косой линией со звездочкой, а заканчиваются звездочкой с косой линией.
/* — начало комментария
.
.
.
.
*/ — конец комментария
Весь текс, который помещен между /* и */ полностью пропускается компилятором.
Однострочный комментарий обозначается двумя косыми линиями и действует в пределах одной строки. Текст перед двумя косыми распознается компилятором как код программы, а после – как комментарий.
// Здесь пишется однострочный комментарий
На практике использование комментариев считается хорошим тоном программирования. В дальнейшем мы будем применять оба их типа.
Директива препроцессора
Следующим элементом программы является строка
#include <avr/io.h>
Эта строка указывает компилятору, что к данному файлу нужно подключить другой файл с именем io.h, который находится в папке avr. В подключаемом файле находится информация о базовых настройках микроконтроллера.
По сути, можно было бы и не подключать файл io.h, а набрать его содержимое вручную, однако это очень неудобно.
Знак # означает, что данная команда – это директива препроцессора. Дело в том, что прежде чем скомпилировать файл компилятору необходимо выполнит предварительную его обработку. Поэтому сначала выполняется некая подготовка файла к компиляции путем добавления некоторых инструкций, прописанных в файле io.h
io – название файла, которое происходит от сокращения input/output – ввод/вывод.
.h – расширение файла, название его происходит от слова header – заголовок.
Теперь все вместе. io.h – это заголовочный файл, в котором записана информация о настройках ввода-вывода микроконтроллера.
Главная функция main
Ниже нам встречается следующая строка:
int main(void)
В данной строке объявляется функция, носящая имя main. С нее начинается выполнение программы. Эта функция является как бы точкой начала всей программы, написанной в текущем файле. Имя main зарезервировано в языке Си, поэтому во избежание конфликтов, таким именем нельзя называть другую функцию, находящуюся внутри данной. main переводится главный, т. е. данная функция является главной.
В синтаксисе языка Си идентификатором функции служат круглые скобки
()
Внутри скобок помещено слово void (void). Оно обозначает пустота. Это указывает на то, что функция main ничего не принимает, т. е. не принимает никаких аргументов. По мере написания более сложных программ, мы детальнее остановимся на этом моменте.
int – это целочисленный тип данных. В данном случае функция работает с целыми числами: как положительными, так и отрицательными. Существуют и другие типы данных, например с плавающей запятой, символьные и др. Более подробно мы будем рассматривать типы данных по мере необходимости или в отдельной статье. Однако для функции main рекомендуется всегда использовать тип данных int, поскольку конструкция int main(void) определена стандартом языка Си и распознается любым компилятором.
Область действия функции определяется фигурными скобками
{
.
. → тело функции
.
}
Код программы, помещенный между открывающейся и закрывающейся скобками, относится к телу функции.
В общем случае любая функция имеет следующую конструкцию:
тип данных имя функции(агрумент)
{
тело функции (код)
}
Функция while
Внутри функции main находится функция while:
while (1)
{
}
While переводится с английского «пока». Это говорит о том, что программа, которая находится в теле данной функции, будет выполняться до тех пор, пока условие истинно. Единица в круглых скобках указывает, что условие истинно, поэтому код программы, написанный в данной функции, будет повторяться бесконечное число раз, т.е. программа будет зациклена. Для чего это делается? Дело в том, что микроконтроллер должен непрерывно выполнять записанную программу. Поэтому программа не может просто взять и оборваться. Микроконтроллер всегда опрашивает порты ввода-вывода либо выдает в них сигналы, даже находясь в ждущем режиме.
Теперь, когда мы рассмотрели основные элементы конструкции программы, давайте посмотрим целиком на базовый шаблон. Без комментариев он имеет следующий вид:
#include <avr/io.h>
int main(void)
{
while (1)
{
}
}
Программирование портов ввода-вывода микроконтроллера ATmega8
Сейчас мы уже можем дополнить программу нужным нам кодом. Первым делом необходимо настроить нулевой бит порта C PC0 на выход.
Мы уже знаем, что МК может, как принимать, так и выдавать сигнал, т.е. выводы (порты) его могут работать как входы и как выходы. Поэтому предварительно нужно настроить вывод МК на соответствующий режим. Для этого в микроконтроллере есть специальный регистр, который называется DDR – direct data register – регистр направления данных.
У каждого порта есть свой такой регистр. Например, регистр порта C называется DDRC, порта B – DDRB, порта D – DDRD.
Чтобы настроить вывод порта на вход в регистр DDR необходимо записать ноль, а на выход – единицу.
Команда настройки нулевого бита порта C выглядит следующим образом
DDRC = 0b0000001;
Данной командой в регистр DDRC записывается двоичное число равное десятичному 1. Префикс 0b идентифицирует данное число, как двоичное.
Двоичная форма записи очень удачно сочетается с количеством битов порта, так как количество битов соответствует количеству выводов порта, а порядковый номер бита отвечает номеру бита внутри порта.
Также можно записать в регистр шестнадцатеричное число:
DDRC = 0x1;
Однако двоичная форма записи более наглядна, поэтому ее мы и будем использовать на начальных этапах программирования микроконтроллеров.
Давайте рассмотрим еще один пример. Допустим нам необходимо настроить нулевой, третий и седьмой биты порта B на выход, а остальные биты на вход. Для этого случая код имеет такой вид:
DDRB = 0b10001001;
С целью закрепления навыков рекомендую потренироваться настраивать разные порты ввода-вывода микроконтроллера на вход и на выход.
Регистр микроконтроллера PORT
После того, как мы настроили нулевой бит порта C PC0 на выход, нужно еще выполнить настройку, чтобы на данном выводе появилось напряжение +5 В. Для этого необходимо установить нулевой бит в регистре PORT. Если бит установлен в единицу, то на выводе будет +5 В (точнее говоря величина напряжения питания микроконтроллера, которая может находится в пределах 4,5…5,5 В для микроконтроллера ATmega8). Если бит установлен в ноль, — то на выводе будет напряжение, величина которого близка к нулю.
Каждый порт имеет свой регистр: порт A – PORTA, порт B – PORTB, порт C – PORTC.
И так, чтобы получить на выводе PC0 напряжение +5 В, необходимо записать такую команду:
PORT = 0b0000001;
Обратите внимание на то, что каждая команда заканчивается точкой с запятой.
Таким образом, чтобы засветить светодиод, нам необходимы всего лишь две команды:
DDRC = 0b0000001;
PORTС = 0b0000001;
Первой командой мы определяем вывод PC0 как вход, а второй устанавливаем на нем напряжение +5 В.
Полный код программы выглядит так:
#include <avr/io.h>
int main(void)
{
DDRC = 0b0000001;
while (1)
{
PORTC = 0b0000001;
}
}
Здесь необходимо заметить следующее: команда DDRC = 0b0000001; выполнится всего один раз, а команда PORTC = 0b0000001; будет выполняться все время в цикле, поскольку она находится в теле функции while (1). Но даже если мы вынесем команду за пределы функции и поместим ее после DDRC = 0b0000001;, светодиод и в этом случае будет светиться все время. Однако, разместив команду PORTC = 0b0000001; в теле while (1), мы делаем явный акцент на том, что светодиод должен светится все время.
Компиляция файла
Теперь, когда код полностью готов, его нужно скомпилировать. Для этого необходимо нажать клавишу F7 или кликнуть по кнопке Build и в выпавшем меню выбрать Build Solution.
Если ошибок в коде нет, то файл скомпилируется, а в нижней части экрана появится запись о том, что проект скомпилирована успешно: Build succeeded.
Таким образом программируются порты ввода-вывода микроконтроллера практически любого типа. Следующий наш шаг – это запись кода в микроконтроллер. Также можно проверить корректность работы кода с помощью программы-симулятора микроконтроллеров – Proteus.
Скачать файлы Программа 1
отличгая статья! начинаю понимать)
супер! Я тоже начал
Таким образом, чтобы засветить светодиод, нам необходимы всего лишь две команды:
DDRC = 0b0000001;
PORTС = 0b0000001;
Первой командой мы определяем вывод PC0 как вход, а второй устанавливаем на нем напряжение +5 В.
Тут помилка. Ми встановлюємо вивід РС0 як вихід ;), а не як вхід.
Точно я тоже заметил.
0b0000001 не хватает одного бита? НЕ?)
порт С не полный. 7 бит.