Дополнительные внешние прерывания, относительно новая штука в периферии AVR. В микроконтроллерах ATmega8/ATmega16 их нет, зато они есть в ATmega88/ATmega168. В официальной документации они описаны в главе 13 "Внешние прерывания". В отличии от обычных внешних прерываний, в дополнительных, одно прерывание отведено на один порт (т.е. на восемь пинов), и в них нельзя выставить условия срабатывания. Прерывание будет генерироваться при любом изменении сигнала, даже если он был изменен программно, самим микроконтроллером.
Компаратор это единственная периферия в AVR которая включена по умолчанию. Поэтому, если он не используется, его следует выключать. Допустимая ошибка (напряжение смещения) не более 40мВ, время отклика не более 0,5 мкс. Рабочие пины: прямой AIN0 и инверсный AIN1. Так же AIN0 называют положительным, а AIN1 отрицательным. Результат заносится в ACO бит регистра ACSR.
Официальный datasheet на ATmega168: http://www.atmel.com/images/doc2545.pdf работа компаратора описана в главе 23.2 на странице 246
Я потратил немного времени на перевод официального руководства, с которым и предлагаю далее ознакомится.
Компаратор управляется через регистр "Analog comparator control and status register" т.е. ACSR:
Ультразвуковые дальнометры HC-SR04 черезвычайно популярны в любительской робототехнике из-за своей дешевизны и простоты. Я тоже не остался в стороне, когда баловался с Arduino, теперь же хочу разобрать работу с сенсором на "низком уровне" и напсать пример работы на чистом Си.
Есть один принципальный момент. Часто работу с сенсором HC-SR04 реализуют через внешние прерывания. Но. В ATmega8 их всего два, и если сенсор будет работать на колесном шасси, то внешние прерывания будут заняты колесными энкодерами. Однако, как я говорил в посте про прерывание захвата, оно работает аналогично внешнему, т.е. есть смысл попытаться его задействовать.
Заглянем в datasheet HC-SR04 и посмотрим на протокол работы сенсора:
ШИМ штука не сложная, по крайней мере, не сложнее чем мигание светодиодом. Принцип тот же: включаешь - выключаешь, и никаких сложных протоколов с контрольными суммами. В июле у меня был пост про таймер в CTC режиме, там если в прерывании начать переключать GPIO то получится вполне полноценный ШИМ. Такой способ хорош тем, что в ШИМ можно превратить любой свободный пин GPIO. Тогда получается, что частота ШИМ будет равна частоте переполнения счетчика, т.е. для 8-битного таймера: (частота кварца)/(предделитель_таймера * 256). Вобще-то, если ШИМ делать вручную, то частоту можно повысить, если в качестве значения таймера брать остаток от деления, но тогда и разрядность ШИМ соответственно понизится. Пример для двухкратного увеличения: (2 % 127)== (129 % 127) == 2.
Однако, есть в AVR аппаратные ШИМ когда все обходится без прерываний, и работает все с двух строчек кода. Называется он Fast PWM.
Для его настойки пондобится лишь контрольный регистр таймера TCCR2:
при поступлении сигнала на захват,
содержимое регистров TCNT1H:TCNT1L
копируется в регистры ICR1H:ICR1L
Что делать? Справедливости ради замечу, что 4-х пиновые вентиляторы лишены этого недостатка, но сейчас речь не о них. Для 3-х пинового вентилятора можно попробывать сделать "умное" управление.
В 8-см вентиляторе на 3300 RPM, датчик Холла срабатывает 110 раз в секунду. Т.е. он (датчик Холла) работает с периодом в девять миллисекунд. Тогда, если мы на время отключим ШИМ, подадим питание 12 Вольт, замерим длительность одного периода, и затем снова включим ШИМ, то мы получим и управление через ШИМ и достоверный контроль за количеством оборотов. Вентилятор, как и все двигатели, очень инерционные штуки и такой фокус никак не скажется на скорости вентилятора, если его проводить не чаще чем раз в две-три секунд. В остальное время, для простого контроля, чтобы быть уверенным, что вентилятор в принципе крутиться, сгодится подсчет имульсов с датчика Холла и без этого фокуса.
Периоды сигналов в AVR можно измерять с помощью т.н. прерывания по захвату. Основные моменты:
за один оборот, датчик Холла
срабатывает дважды
Обычно внешние прерывания разбирают на кнопках, но у меня есть более интересный пример: счетчик оборотов компьютерного кулера.
Напомню, что подсчет оборотов ведется через датчик Холла, который является неотъемлемой частью компьютерного вентилятора. В данном случае пойдет речь о трех-пиновым вентиляторе. схема подключения взята из одного из предыдущих постов, когда счетчик писался для Arduino. В качестве шаблона кода взят пример, из прерыдущего поста про фоторезистор. Из примера, были уделены три строчки относящиеся к АЦП.
В официальном руководстве на ATmega8, внешние прерывания(External Interrupts) описаны на странице 66. Они имеют более высокий приоритет перед другими прерываниями. Управляются регистром MCUCR:
Попробуем сделать датчик освещености. В комбинации с модулем RTC такой датчик может управлять освещением и подсветкой в системах типа: "умный дом". Датчик будет на фоторезисторе, сопротивление которого обратно пропорционально уровню освещености. Фоторезистор будет подключаться по схеме делителя напряжения, где в верхнее плечо будет установлен постоянный резистор 10K, а в нижнее сам фоторезистор. Нулевая точка будет поключена к пину ADC0 микроконтроллера. По такой же схеме можно подключать терморезистор или клавиатурную сборку на тактовых кнопках, где к каждой кнопке будет подключен резистор с каким-то своим индивидуальным значенем. Тогда, замеряя разность потенциалов, можно будет узнать какая имено кнопка была нажата.
Но вернемся к фоторезистору. Модель котрая мне попалась под руку - VT93N2. Даташит на него представлен ниже:
В одном из предыдущих постов, я рассказывал про подключение термопары к Arduino. Теперь настало время рассмореть подключение к AVR микроконтроллерам на чистом Си, благо, как выяснилось, это совсем не сложно.
Напомню, что термопара подключается через адаптер MAX6675, который в свою очередь подключается к микроконтроллеру через SPI интерфейс.
После I2C, SPI интерфейс скорее всего покажется очень простым. Если расмотреть аппаратную реализацию SPI, то там есть регистр данных SPDR, записью или чтением с которого и осуществляется вся работа c SPI.
Программная реализация, как выяснилось, не намного сложнее, но сначала о том, что такое SPI. Фирменный аппнот к SPI можо найти на сайте Atmel: AVR151: Setup And Use of The SPI
рассмотрим схему подключения взятую оттуда:
Если посмотреть на исходник в предыдущем посте, то можно заметить, что программная часть работы с UART "кочует" из поста в пост, и правильно было бы выделить ее в отдельный файл, как впрочем и реализацию работы с TWI модулем. Развивая мысль, мы придем к необходимости, какой-то библиотеки, куда можно будет скидывать собственные наработки по работе с тем или иным модулем. По правде говоря такоя библиотека уже есть, называется: Procyon AVRlib. Изучение ее безусловно всем рекомендую, но... она стара, как баба-яга, а библиотека для микроконтроллера не шибко сложная вещь, и вероятно каждый, по мере изучения avr-архитектуры, захочет написать собсвенный аналог "с трехмерными шахматами и нейронными диструктурами".
Итак, цель надеюсь понятна, для начала напишем файл проекта Makefile, это будет попроще. Затем, что бы код для AVR можно было писать в Qt Creator, сделаем еще CMakeLists.txt
В качестве "подопытного" кода возмем пример из предыдущего поста. Выделим из него модули UART и TWI, тогда сруктура директорий будет примерно такой:
После UART, реализация TWI модуля на AVR кажется довольно корявой и без понимания I2C протокола будет не просто его освоить. Однако, если разобраться с "софтовой" эмуляцией протокола, то работа с TWI модулем уже не составит труда.
Не последне место в этом списке должно быть у официального аппнота: AVR315: Using the TWI module as I2C master
Если открыть руководство для ATmega8, на странице 156 раздел "Two-Wire Serial Interface", то там даже будет примерный набросок программы для работы с TWI: