Библиотека Arhat.h - "расширение Cyberlib"
для эффективного управления на AVR. Дополнение к ИДЕ. Работа с пинами, таймерами, прерываниями и PWM.
Архив распаковывается в папку libraries как обычная библиотека Ардуино. Далее можно смотреть примеры и пробовать.
В силу невозможности выложить код под спойлер, добавил в пост архив со всей библиотекой, в той части в которой она совместима с Ардуино ИДЕ. В связи с чем, возможны некоторые накладки с описаниями, ссылками на отсутствующие куски в коде.
Отсутствует: "свой" код таймера Т0 для функций времени millis(), micros() и пр. Обработчик этого прерывания сильно конфликтует со встроенным обработчиком в Wiring и компилировать скетчи получается только с большим бубном, особенно после выхода версии 1.6.7 кажется. Где в ИДЕ добавлен "builder" и насильно впихивается в скетчи инклуд Arduino.h первой строкой. До той версии, этот инклуд пихался последним, что позволяло отключать его использование. Увы, сие изменение возникло практически сразу после того как отправил разработчикам Wiring код этой библиотеки на посмотреть и улучшить, добавив возможность эффеткивной компиляции в скетчи.
2. Все имена функций тут - разведены (свои) от типовых из Wiring. Одна из первоначальных целей написания как раз и состояла в том, чтобы подключая эту библиотеку можно было существенно уменьшать размеры программ и улучшать их быстродействие от 10 до 100раз.
Библиотека имеет существенное ограничение в использовании - точно такое же как и исходная - Cyberlib, а именно: все пины предполагаются заданными константно или через #define или через префикс const! С номерами пинов в переменных она работать не будет точно также!
В библиотеке есть настроечные файлы для микроконтроллеров ATmega328 и всех его клонов и ATmega2560 и всех его клонов. Тут вторые ограничены пинами типовой платы Arduino Mega 2560 r3. Если у Вас MegaCore или плата на базе всех ножек микроконтроллера, то можно раскомментировать кусок описаний в конце arhat_pins2560.h
1. Работа с пинами:
Есть базовые макросы pin0 .. pin69, pinLed, которые расписаны в файлах настройки на микроконтроллер arhat_pinsXXX.h. Можно дополнить своим файлом по образцу и в arhat.h воткнуть #ifdef также по образцу, для выбора нового файла настройки пинов под Ваш микроконтроллер. Не проблема ни разу, просто муторно.
Ногодрыги обеспечиваются макросами:
pinModeOut(p), pinModeIn(p), pinOutHigh(p), pinOutLow(p), pinOut(p,v), pinRead(p), pinModePullup(p) -- их смысл понятен из названий. Это в общем-то замена для
pinMode(), digitalWrite() и digitalRead() функций Wiring (раньше они так и переименовывались, дабы не править скетчи совсем).
Работа с таймерами
базовая часть, практически не нужна:
pwmGetTimer(p) -- получить номер таймера по номеру его пина. Пин p не "какой попало" а только тот где есть таймер: [2..13,44,45,46, T1C]
pwmGetChannel(p) -- Получить букву(!) канала таймера по его номеру. Пин p - аналогично выше.
timerCount(t) -- Получить регистр текущего счета таймера. Тут уже принимается числовой номер таймера: 8/16 битовые.
timerControl(t,r) -- p:[0,2,[1,3,4,5]], r:[A,B[,C]] -- буква! из пред. макроса. Чтение/Установка регистра ШИМ таймера и канала соответсвенно.
timerCompare(t,r) -- Регистр сравнения таймера. Аналогично передается номер таймера (число) и буква(!) канала.
timerCapture(t) -- Регистр захвата для 16-битных таймеров. p:[1,3,4,5].
timerIMask(t,v,b) -- Регистр маски прерываний. t:[0,2[,1,3,4,5]] v:[OVF,COMPA,COMPB[,COMPC,CAPT]], b:[0,1] -- запретить/разрешить.
timerIFlag(t,v) -- Читать флаг состояния прерывания таймера t:[0,2[,1,3,4,5]] v:[OVF,COMPA,COMPB[,COMPC,CAPT]].
timerISR(t,v) -- make interrupt vector name t:[0,2[,1,3,4,5]] v:[OVF,COMPA,COMPB[,COMPC,CAPT]]. Это если забылось как оно пишется в interrupt.h
prescalerMode(pr) -- Перевод коэффициента делителя в код режима прескалера: 64 --> 3. Удобства для.
Это всё, если надо что-то делать с таймером сильно особенное. На практике не пригодилось практически ни разу. Поскольку это макрокоманды для препроцессора, которые на самом деле формируют текст требуемых вызовов, то тут надо указывать конкретную букву канала таймера, как будто это "имя переменной". На самом деле, она тупо "приклеивается к имени другого макроса, в результате чего получается имя макроса, который уже и компилируется компилятором. Своеобразная система "темплейтов" на Си.
Настройка 16-и битных таймеров для прямой работы с серводвигателями:
timerSetServo(t,pwmPinMask) Установка 16битного таймера и его каналов в типовой ШИМ для серво моторов. Ноги на вывод устанавливать отдельно!
pwmSetServo(p1) -- Установка одной ноги на ШИМ и её таймера в типовой режим сервоШИМа: 50Гц. Для последующего канала этого же таймера достаточно вызвать pwmSet(p).
Собственно работа с серводвигателями у нас и оказалась единственно полезным применением этих макросов. Детально читать описания к этим макроопределениям в arhat.h. Их задача - перевод таймера в режим ШИМ с типовой частотой для серв 50Гц и попутно настройка каналов для работы с серводвигателем функцией analogWrite() или макросами ниже напрямую.
Работа с ШИМ:
pwmPinMode(p,m) -- тут p:[2..13,44,45,46,T1C] - ШИМ нога, m[PWM_DISABLE,PWM_TOGGLE,PWM_NORMAL,PWM_INVERSE] - режим ШИМ.
pwmSet(p) -- установить типовой (500Гц) режим ШИМ для заданной ноги (см. выше) "как в Wiring"
pwmOff(p) -- Выключить ногу из ШИМ. Нога остается "на вывод". Весь таймер - не отключаем.
pwmWrite(p,v) -- местный analogWrite(): out PWM p:[2..13,44,45,46,T1C], v:[0..255] with 250kHz. Аналог этой функции 1-й командой.
В архиве есть примеры как это все использовать. Дополнительно там же есть папка doc, в которой лежат даташиты на 328 и 2560 серии микроконтроллеров, дабы не искать, если что-то забылось. Там же есть тест Drystone (оригинал, так и не адаптировал для AVR).