Юрий Ревич - Занимательная электроника
В архитектуре AVR 8-разрядным счетчикам-таймерам присвоены номера 0 и 2, а 16-разрядным — 1, 3 и далее. Некоторые 8-разрядные счетчики (обычно Timer 2, если их два) могут работать в асинхронном режиме от отдельного тактового генератора, причем продолжать функционировать даже в случае «спящего» состояния всей остальной части МК, что позволяет использовать их в качестве часов реального времени.
При использовании счетчиков-таймеров как обычных счетчиков внешних импульсов (причем возможна реакция как по спаду, так и по фронту импульса) частота подсчитываемых импульсов не должна превышать половины частоты тактового генератора МК (причем при несимметричном внешнем меандре инструкция рекомендует еще меньшее значение предельной частоты — 0,4 от тактовой). Это обусловлено тем, что при счете внешних импульсов их фронты обнаруживаются синхронно (в моменты положительного перепада тактового сигнала). Кроме того, стоит учитывать, что задержка обновления содержимого счетчика после прихода внешнего импульса может составлять до 2,5 периода тактовой частоты.
Это довольно сильные ограничения, поэтому, например, использовать МК в качестве универсального частотомера не очень удобно — быстродействующие схемы лучше проектировать на соответствующей комбинационной логике или на ПЛИС (программируемых логических интегральных схемах).
При наступлении переполнения счетчика возникает событие, которое может вызывать соответствующее прерывание. 8-разрядный счетчик Timer 0 в ряде случаев этой функцией и ограничивается. Счетчик Timer 2, если он имеется, может также вызывать прерывание по совпадению подсчитанного значения с некоторой заранее заданной величиной. 16-разрядные счетчики — более «продвинутые» и могут вызывать прерывания по совпадению с двумя независимо заданными числами А и В. При этом счетчики могут обнуляться или продолжать счет, а на специальных выводах при этом могут генерироваться импульсы (аппаратно, без участия программы).
Кроме того, 16-разрядные счетчики могут осуществлять «захват» (capture) внешних одиночных импульсов на специальном выводе. При этом может вызываться прерывание, а содержимое счетчика помещается в некий регистр. Сам счетчик при этом может обнуляться и начинать счет заново или просто продолжать счет. Такой режим удобно использовать для измерения периода внешнего сигнала или для подсчета неких нерегулярных событий (вроде прохождения частиц в счетчике Гейгера). Немаловажно, что источником таких событий может быть и встроенный аналоговый компаратор, который тогда используется как формирователь импульсов.
Все счетчики-таймеры могут работать в так называемых режимах PWM, т. е. в качестве 8-, 9-, 10- или 16-битных широтно-импульсных модуляторов (ШИМ), причем независимо друг от друга, что позволяет реализовать многоканальный ШИМ.
В технической документации режимам PWM, в силу их сложности, многовариантности и громоздкости, посвящено много страниц. Простейший вариант использования этих режимов — воспроизведение звука. Их также можно задействовать для регулирования мощности или тока (например, при зарядке аккумуляторов), управления двигателями, выпрямления сигнала, при цифроаналоговом преобразовании.
В этом издании я не буду рассматривать такие применения МК AVR, потому что они значительно упростились с появлением платформы Arduino, и им посвящено множество доступных интернет-ресурсов.
Кроме таймеров-счетчиков, во всех без исключения AVR-контроллерах есть сторожевой (Watchdog) таймер. Он предназначен в основном для вывода МК из режима энергосбережения через определенный интервал времени, но может использоваться и для аварийного перезапуска МК. Например, если работа программы зависит от прихода внешних сигналов, то при их потере (например, из-за обрыва на линии) МК может «повиснуть», а Watchdog-таймер выведет его из этого состояния.
Последовательные портыПоследовательные порты для обмена данными с внешними устройствами — важнейшая составляющая любого МК, без них его «общение» с внешним миром резко ограничено. Последовательными их называют потому, что в них в каждый момент времени передается только один бит (в некоторых случаях возможна одновременная передача и прием, но все равно только по одному биту за раз). Самое главное преимущество последовательных портов перед параллельными (когда одновременно производится обмен целыми байтами или полубайтами-тетрадами) — снижение числа соединений. Но оно не единственное — как ни парадоксально, но последовательные интерфейсы дают значительную фору параллельным на высоких скоростях, когда на надежность передачи начинают влиять задержки в линиях. Последние невозможно сделать строго одинаковыми, и это одна из причин того, что последовательные интерфейсы в настоящее время начинают доминировать (типичные примеры: USB и Fire Wire вместо LPT и SCSI или Serial ATA вместо IDE).
В микроконтроллерных устройствах с нашими объемами данных, конечно, скорость передачи нас волнует во вторую очередь, но вот количество соединительных проводов — очень критичный фактор. Поэтому все внешние устройства, которые мы далее станем рассматривать, будут иметь последовательные интерфейсы (кроме дисплеев для отображения информации, для которых, увы, последовательные интерфейсы встречаются лишь в моделях достаточно высокого уровня).
Практически любой последовательный порт можно имитировать программно, используя обычные выводы МК. Когда-то так и поступали даже в случае самого популярного из таких портов — UART. Однако с тех пор МК обзавелись аппаратными последовательными портами, что, впрочем, не означает необходимости их непременного использования. Легкость программной имитации последовательных портов — еще одно их достоинство.
Из всех разновидностей портов, которые могут наличествовать в МК AVR, мы особенно обратим внимание на UART (Universal Asynchronous Receiver-Transmitter, универсальный асинхронный приемопередатчик). UART есть основная часть любого устройства, поддерживающего протокол RS-232, но и не только его (недаром он «универсальный») — например, промышленные стандарты RS-485 и RS-422 также реализовываются через UART, т. к. они отличаются от RS-232 только электрическими параметрами и допустимыми скоростями, а не общей логикой построения.
В персональных компьютерах есть СОМ-порт, который работает по тому же протоколу RS-232, и узел UART точно так же является его базовой частью. Поэтому UART служит основным способом обмена данными МК с компьютером.
Отметим, что отсутствие СОМ-порта в большинстве современных моделей ПК не является препятствием — существуют переходники USB-COM, а в настольную модель можно вставить дополнительную карту с СОМ-портами. О том, как обращаться с UART на практике, рассказывается в главах 21 и 22, применительно к платформе Arduino — программировать такой обмен на ассемблере гораздо сложнее (хотя и надежнее, см. далее). В главе 22 мы увидим, что существуют простые и при этом достаточно надежные способы организовать передачу через последовательный порт по радиоканалу, что позволяет обойтись вообще без проводов.
Кроме UART, почти все МК AVR содержат самый простой из всех последовательных портов — SPI (Serial Peripheral Interface, последовательный периферийный интерфейс). Об устройстве SPI упоминалось в главе 16. Его принципиальная простота сыграла отчасти дурную роль — трудно встретить два устройства, где протоколы SPI полностью совпадают, обычно обмен по этому порту сопровождается теми или иными «наворотами». Следует отметить, что программирование AVR также осуществляется через SPI, однако в общем случае этот интерфейс и SPI для обмена данными — разные вещи, хотя в большинстве случаев выводы у них одни и те же.
Кстати, всем знакомые карты памяти («флэшки») также адресуются через протокол, очень близкий к SPI.
Кроме этих портов, часто применяется очень простой аппаратно, но более сложный с программной точки зрения и довольно медленный интерфейс 12С (в терминологии Atmel AVR он называется TWI (Two-Wire Interface, двухпроводной интерфейс). С его помощью можно общаться со многими устройствами: часами реального времени, компасами, датчиками, некоторыми разновидностями памяти. Мы рассмотрим его опять же в главах, посвященных Arduino.
В AVR имеется 10-разрядный АЦП последовательного приближения (см. главу 17). Работа с ним имеет довольно много нюансов, и мы ее подробно рассмотрим в главе 20. В главе 22 вы увидите, насколько Arduino упрощает этот процесс. И вообще, некоторые другие узлы МК семейства AVR мы рассмотрим по ходу изложения конкретных схем — так будет нагляднее. Сейчас же мы закончим затянувшееся знакомство с микроконтроллером и обратимся к вопросу о том, как его программировать. Следующие две главы мы посвятим элементарным сведениям о программировании МК на ассемблере, а далее перейдем к языкам высокого (и даже сверхвысокого) уровня. Так вы сможете наглядно сравнить и даже при желании «пощупать руками» преимущества и недостатки того и иного подхода и границы их применимости.