Моя борьба
(с микроконтроллерами)
Содержание:
Введение
С чего все началось
Выбираем среду разработки
Выбираем программатор
Какой MCU выбрать?
Почему MCU 8-битный и от Atmel?
Практикум — несколько примеров
А что у них с разгоном?
Идем дальше или не идем?
Месяца три-четыре назад появился у меня первый микроконтроллер от Atmel - Atmega 328P, в комплекте с небольшой платкой Arduino Duemilanove, с необходимой обвязкой, гнездами для I/O и мостом RT232RL для подсоединения к PC по USB. Об этом написано подробнее в статье «Моя домашняя лаборатория», и в то время я находился под эйфорией приобретения этой техноигрушки (на которые весьма падок, несмотря на давно уже не детский возраст).
Вообщем, группа товарищей-итальянцев, уже не первый год выпускающих изделия под маркой Arduino, предлагает новичкам простое и доступное устройство и соответствующее программное обеспечение для старта в мир микроконтроллеров. Автор этих строк, хоть и новичок в изделиях фирмы Atmel, но в прошлом веке имел опыт общения с микроконтроллерами — советскими клонами популярных 8035/8048/8051. Кстати, 8051 не собирается сдавать позиции и до сих пор — масса прикладного кода, неприхотливость и невысокая цена делает его крайне востребованным. Более того, он есть почти на каждой материнской плате для PC, конечно, не в виде отдельного корпуса, а внедренный в состав других микросхем.
И все бы было хорошо с Arduino, если бы не несколько «но».
Внешняя «красивость» Arduino, направленная на привлечение потенциальных покупателей, имеет обратную сторону. Плата имеет собственную нумерацию «цифровых» и «аналоговых» портов, которая отличается от оригинальной для MCU AVR, что создает неудобства тем, кто все же иногда читает документацию, а для тех, кто не читает, создает иллюзию вседозволенности и равнозначности выводов. Для простых задач это не составляет проблем, но они могут возникнуть тогда, когда их меньше всего ждешь, например, если кто-то надумает создавать критичные по времени программы, набрав шину данных из нескольких разных физических портов.
Во-вторых, программный интерфейс, если вы уже работали в интегрированных средах разработки от известных производителей, сразу бьет по глазам и создает стойкое впечатление ущербности продукта. Теоретически, с этим можно было бы и смириться, так как для разработки программ можно использовать и другие Си-компиляторы, поскольку Arduino использует популярные библиотеки avrc-lib. Но сама разбивка используемого языка программирования на базовую, расширенную и полную версии представляет, на мой взгляд, не лучшее решение.
Так как зажигать светодиоды — задача ниже моего достоинства (хоть сам я и не программист), то попробовал начать с разработки 1-wire интерфейса для подключения датчиков температуры и обработки результатов на ПК. После успешного решения этой проблемы на языке Си в среде Arduino, было принято решение в дальнейшем от Arduino отказаться. Как в аппаратном, так и в программном плане. Хоть сама плата и красивая, но самосбор подобного изделия обойдется в два раза дешевле, правда, может получиться чуть менее симпатично. Кроме того, разработчики намеренно добавили трудности для создания прототипов, подключаемых к разъемам I/O платы Arduino, сдвинув один из разъемов с шага сетки 2.54мм, тем самым искусственно стимулируя спрос на специализированные платы прототипов. Эта некрасивая мелочность и стала последней каплей.
Но, «пощупав» микроконтроллер, захотелось продолжить знакомство с AVR, но уже без Arduino. Так как познаний в области MCU AVR нет никаких, садимся за документацию, попутно подбираем среду разработки и оборудование для прототипов и экспериментов.
Тут выбор был недолгим. Лучше всего понять и почувствовать новый микроконтроллер можно на ассемблере. Это самый простой и понятный язык, ничего лишнего и все в твоих руках. Единственный минус — если нет готовых библиотек, то некоторые вещи придется делать очень долго. К примеру, арифметика чисел с плавающей точкой, ввод-вывод с различных устройств, но это трудности временные. Как и что бы не говорили апологеты «правильного» программирования, при прочих равных условиях (имеется в виду наличие необходимых библиотек и квалификация пользователя), программа не супер-мега размера на ассемблере делается не дольше, но всегда будет быстрее и компактнее. Впрочем, не язык программирования красит программиста, а творения его, сделанные на том языке, который он знает. Хорошую и полезную программу можно сделать на любом языке.
Итак, ассемблер. Производитель MCU предлагает свою версию IDE — Avr Studio, с набором необходимых заголовочных файлов для всех выпускаемых 8-битных MCU от AVR. Использование этих заголовочных файлов обеспечивает работоспособность всех примеров из руководства , что дает возможность использования мнемонических наименований различных регистров вместо трудно запоминающихся шестнадцатеричных адресов, и соответствующих мнемоник для относящихся к ним битам. Хотя нужно отметить, что ошибок и неточностей хватает и в руководствах, выпущенных даже в июне-июле 2009 года как обновления для давно уже выпускаемых MCU.
Первое впечатление от IDE AVR Studio осталось положительным. Кроме макроассемблера, можно работать и с C++, но нас сейчас интересует только ассемблер. Имеется встроенный отладчик и эмулятор, что дает достаточный, на первых порах, инструментарий для наших нетребовательных нужд, кроме того, очень хорошо для оптимизации кода, что считаются циклы процессора и на каждом останове можно это увидеть.
Кстати, редактированием конфигурационного файла можно добавить подсветку синтаксиса и собственным данным, например, можно сделать так, чтобы выбранные макросы подсвечивались тем же цветом, что и встроенные команды.
В MCU при отладке нужно будет часто перезаписывать программу в его флэш-память. Для этого используется несколько интерфейсов, самый простой из которых — последовательный, задействующий у MCU блок выводов SPI и сброс. Применяются и другие методы, например, «высоковольтное», «параллельное» программирование, программирование через интерфейс JTAG (он есть не у всех MCU) и собственный двухпроводный интерфейс Atmel.
AVR Studio поддерживает всю гамму фирменных программаторов и отладочных плат, но такие устройства относительно дороги. В любительских условиях целесообразно использовать ISP-программаторы, самый простой из которых представляет собой переходник с параллельного порта PC с несколькими ограничивающими резисторами, иногда и с промежуточным буфером на 74хх245. Но мы воспользуемся другим популярным вариантом, AVRDude, многочисленные клоны которого подробно описаны в интернете. Для этого приобретем полуфабрикат от польского распространителя электронного ширпотреба www.sklep.avt.pl , AVT5172A+, в состав которого входит двухсторонняя PCB и запрограммированный MCU:

PCB программатора

Программатор в сборе
Если вы планируете работать в среде OC Windows Vista, то желательно установить стабилитроны на 3.3В после резисторов, подключенных к сигнальным выводам разъема USB.
Собранная плата некоторое время находилась в свободном размещении, для разных нужд было сделано несколько плоских кабелей с IDC разъемами, в том числе и переходник с 10-контактного на более современный 6-контактный разъем. Но было не очень удобно, так как программатор приходилось подключать к макетной плате проводниками, вставляемыми в IDC-разъем:

Установка программатора в корпус, наподобие фирменного AVR ISP, проблему кучи проводов не решает. Выход был найден после приобретения прототипной платы, состоящей из трех таких макетных плат, как на фотографии вверху. Программатор был закреплен в свободном месте на пластмассовом корпусе прототипа:

Следующим шагом нужно было убрать ненадежное подсоединение отдельными проводами от разъема плоского кабеля до элементов схемы. Для этого нужно смастерить специальный переходник, для чего потребуется ответная часть двухрядного разъема, кусочек от текстолитовой платы-прототипа и шестиконтактная однорядная гребенка, то есть, кроме трех сигналов SPI и сброса от программатора будет подаваться и напряжение питания. Так как программатор сам запитывается от разъема USB компьютера, то это ограничивает потребляемый ток схемой на прототипе примерно до 300мА, что в большинстве случаев позволяет обойтись без внешних источников питания. В необходимых случаях разрабатываемую схему можно запитать и от отдельного источника, для чего на пластмассовом корпусе прототипа есть 4 разъема, к которым можно подсоединить и клемму под винт, и штекер. При этом нужно снять перемычку на программаторе, через которую на программируемую схему подается напряжение.
Вот как выглядит переходник:

Переходник
Соединение на обратной стороне, для скорости, было выполнено не перемычками, а чудовищным слоем припоя, немного не эстетично, зато очень быстро, благо практически все соединения — прямые линии, за исключением земли и питания.
Программатор установлен стационарно, ничего не мешает (разве что было бы лучше, если USB разъем располагался бы на длинной стороне PCB программатора).

Но программатор — не только hardware, необходимо и программное обеспечение. С AVR Dude
прекрасно можно работать в режиме командной строки, но проще было бы использовать простенькую графическую оболочку, если она будет обеспечивать минимальные дополнительные манипуляций с мышью и клавиатурой, то есть чтобы процесс программирования MCU выполнялся бы с наименьшими усилиями. Такая оболочка для программатора была найдена на просторах интернета — товарищ из Ирана сделал, на мой взгляд, лучший вариант — Khazama AVR Programmer http://www.khazama.com/project/programmer/ . Лучший потому, что для того, чтобы запрограммировать контроллер после компиляции в AVR Studio достаточно одного щелчка мыши по кнопке, к тому же пара других подобных программ с моей версией программатора просто не заработала с первого включения. Khazama AVR Programmer обеспечивает программирование фьюзов, несколько опций программатора, просмотры файлов, и имеет опцию окна «постоянно поверх других», которая у меня всегда включена и для заливки программы достаточно просто нажать на кнопку Auto Program:

Программа запоминает и использует при следующем включении необходимые *.hex и *.epr файлы и свои координаты. Пару раз после включения программа не появлялась на рабочем столе — в ее конфигурационном файле «setting» оказывались записанными некорректные значения координат X и Y, тогда нужно просто записать там 0,0 и, после запуска, перетащить окно в требуемое место; для меня комфортнее всего для этого подходит правый нижний угол IDE AVR Studio:

(кликните по картинке для увеличения)
AVR Studio и окно программатора
К моему удивлению, программа не поддерживает программирование фьюзов для некоторых видов процессоров, по которым давно уже имеется документация. Вероятно, автор не смог получить такие MCU в свое распоряжение и без практической проверки не внедрил такую поддержку, хотя сама основная программа прошивается без проблем. В моем случае неприятным сюрпризом явилась невозможность перепрограммирования служебной области у Atmega328P.

Необходимость в Atmega328P возникла потому, что имеющиеся у меня младшие модели MCU серии Atmega 168 и 88 имеют только 1КБ SRAM на борту. А для программирования графического дисплея был нужен (для экспериментов по созданию графической библиотеки) объем RAM, равный графической памяти обычного монохромного дисплея размером 128х64 точки, то есть 1КБ, плюс примерно еще столько же должно оставаться под дополнительные нужды и стек. Некоторое время тренировался на Atmega88 c 1КБ RAM, используя дополнительный буфер только под половину экрана:

Объем RAM 2КБ и выше имеют те модели AVR, где установлено 32КБ флэш памяти. Самый современный из них, имеющий исполнение DIP, это как раз Atmega328P. Можно, конечно, воспользоваться внешней памятью, применив соответствующий MCU, например, 8515, но это уже совсем другая песня. В принципе, такой MCU, внешняя SRAM и регистр-защелка серии 573, нужный для демультиплексирования шины адреса-данных, тоже имеется, он используется в качестве прототипа для устройства на базе планарного Atmega128, которое пока в разработке.
Прежде, чем приступить к программированию фьюзов Atmega328P, стоит упомянуть о полезной программе, онлайновому калькулятору фьюзов и лок-битов микропроцессоров AVR. Его можно найти по адресу http://www.engbedded.com/fusecalc . Выбрав нужный вам MCU, легко получить нужные коды и, более того, приводится уже готовая строка для присоединения к командной строке AVR Dude, при программировании через выбранный программатор:

Тройной клик на верхней строке ее выделяет (это можно сделать и обычным выделением), и ее можно вставить в командную строку:

(кликните по картинке для увеличения)
Выполнение командной строки
Не стоит пугаться ошибки верификации — об этом об этом и на предыдущей картинке красным цветом специально выделено. Программируемые регистры имеют неиспользуемые биты, которые будут читаться нулями, не зависимо от того, что туда будет записываться, то есть, в данном случае, после программирования efuse как 0xff (кстати, программирование байта в EEPROM значением 0xff означает просто ничего не делать) при чтении получено 0x07, то есть пять старших битов не установлены, что на самом деле не является ошибкой.
В данном случае Atmega328P запрограммирован на работу от внутреннего RC осциллятора 8МГц и подачей полной частоты на вывод 14 микросхемы (это бывает необходимо при мультипроцессорных конфигурациях, с этого вывода снимается тактовые импульсы для подачи на другие элементы схемы, а в нашем случае это используется для быстрого контроля правильности наших действий — после окончания программирования на этом выводе с помощью осциллографа можно увидеть меандр 8МГц. Кроме того, так будет удобно и калибровать внутренний RC-генератор, так как по умолчанию его точность установки 10%, а реально можно добиться точности на два порядка выше).
После проверки работоспособности MCU и его точной калибровки, если это необходимо (желательно все же ее провести, так как один из четырех MCU Atmegа88 попался с частотой по умолчанию в 7.2МГц, остальные были примерно на 8.1МГц), снимаем подачу тактовой частоты на 14-й вывод, выполнив еще одно программирование :

Фактически, мы вернулись к заводским настройкам. Так как цоколевка и назначение выводов во всей серии MCU Atmegа 48/88/168/328 совпадает, то все это можно проделать на всей этой серии микроконтроллеров, включая индексы P, A и PA, поставив соответствующие данные, полученные из калькулятора или определенные самостоятельно. Для простых Atmegа8, цоколевка также совпадает, но функции вывода тактовой частоты на 14-й вывод нет. Конфигурационный файл conf.txt – это просто переименованный стандартный, в котором прописана поддержка процессора MCU 328P.
Таким образом, плата прототипа, программатор, MCU и среда разработки определены.
Ничего против MCU других производителей и другой разрядности не имею. Более того, несколько раз сдерживался, чтобы не купить игрушки других производителей, к примеру, Propeller от Paralax или что-нибудь на ядре Cortex М3 или семитысячную атмелку.
Причина выбора Atmel предельно банальна — цена на нашем локальном рынке. MCU PIC от Microchip, в сравнении с сопоставимыми моделями Atmega, стоят в среднем в два раза дороже. А потом, естественно, уже срабатывает сила привычки. Но несколько пробных программок я написал и для PIC.
Кстати, существует интересный документ, ответ компании Microchip на громкие рекламные заявления корпорации Atmel по поводу выпуска ее первых 8-разрядных MCU. В частности, Atmel заявила, что это первые в мире микроконтроллеры, хотя Microchip на тот момент уже год как выпускала MCU с подобной функциональностью. Познавательно почитать и техническое сравнение, которое выглядит совсем вопреки PR-компании Atmel. Впрочем, документу уже много лет и перечисленные недостатки в значительной степени устранены и на тех и других MCU можно решать соответствующий их вычислительной мощности класс задач (для примера — по этому параметру MCU Atmega8 примерно соответствует процессору Intel 80286). Но следы пиарщиков Atmel видны и сегодня — наверное, была поставлена задача подавить конкурента расширенным в четыре раза (это у RISC архитектуры!) набором инструкций. Анализ операционного кода сразу показывает, что для ряда операционных кодов просто добавлена новая мнемоника (к примеру OR Rd,Rd и TST Rd, EOR Rd,Rd и CLR Rd и др.) что явно не соответствует понятию «новая инструкция», а вот некоторых команд действительно не хватает, например, сложения с константой, косвенных операций со стеком и т.д., хотя все это и не принципиально. Например, сложение с константой для любого регистра для 8-битной арифметики легко заменяется имеющейся командой вычитания константы.
Так же ценой определяется и то, что пока в экспериментах используются 8-битные процессоры. Например, 16-битный MCU ECOG1X14B5 от Cyаn стоит столько же, сколько и Atmega328P. При этом, ECOG1X14B5 имеет несравненно лучшие характеристики, вот таблица сравнения по некоторым параметрам:
Параметр | ECOG1X14B5 | ATmega328P |
---|---|---|
Флэш память | 512КБ | 32КБ |
SRAM | 24КБ | 2КБ |
Тактовая частота | 70МГц | 20МГц |
Memory Management | Есть | Нет |
External Memory | Есть | Нет |
Кэш команд | Есть | Нет |
USB интерфейс | Есть | Нет |
Ethernet интерфейс | 10/100 | Нет |
Smart Card Interface | Dual | Нет |
I2S digital audio | Есть | Нет |
LCD controller | 32х4 | Нет |
Таймеры | 13 | 4 |
По техническим параметрам, при равной стоимости изделий, MCU Atmel и близко не стоит с MCU Cyan. Почему же сразу не отбросить в сторону 8-разрядные MCU Atmel?
К сожалению, кроме стоимости самого MCU нужно учитывать и «стоимость владения», то есть стоимость оборудования для создания прототипов. Более развитые MCU обычно не имеют корпусов типа DIP, с которыми прекрасно можно работать на обычных макетных платах-прототипах. Подобные MCU имеют 100 выводов и более и конструктив корпуса QPFN или даже BGA, что в несколько раз повышает стоимость создания прототипов и для любительского конструирования такие затраты не всегда приемлемы.
Кроме того, более сложные MCU, обладая повышенным набором интерфейсов, внедряют сложные механизмы управления памятью, многочисленные режимы DMA и другие усовершенствования, что повышает и сложность создания программ.
Рассматривая одну тенденцию, когда разработчики повышают разрядность и производительность своих MCU, соответственно увеличивая энергопотребление и размеры за счет дополнительной необходимой обвязки, можно заметить и другую, когда архитектурные решения платформы х86 спускаются по производительности от «обычного» PC, в направлении сверху вниз, в виде, например, picoITX решений. Конечно, для PDA и малогабаритных медиаплееров решения x86 пока не могут конкурировать с RISC-процессорами, но в промышленном сегменте, при создании web-приложений конкуренция обостряется. Рано или поздно, но, с развитием технологий, постепенно границы между платформами будут размываться.
К примеру, вот вид референсной платы Atmel на базе 32-битного MCU AP7000:

Примерно аналогичная по стоимости и назначению плата (практически, готовый web-сервер) под Cyan, правда с одним сетевым портом и без установленного кардридера, выглядит так:

С другой стороны, если использовать 8-битные MCU серии Xmega, или даже Atmegs128 с внешней SRAM, Ethernet контроллером, то PCB будет выглядеть не намного проще.
PicoITX решение VIA EPIA PX10000G, размером 10х7.2см стоит заметно подороже, но зато это уже относительно полноценный x86-компьютер:

Но прежде, чем создавать такие вещи на продвинутых MCU, нужно попрактиковаться на чем-нибудь попроще, для наших задач начального уровня выбор 8-разрядных MCU AVR вполне логичен. Соответственно, понятен и класс задач, решаемый такими устройствами, это, прежде всего, несложная автоматика, обработка данных датчиков, коммуникация и вывод информации на LED-индикаторы, текстовые или графические дисплеи с небольшим разрешением и глубиной цвета. Для просмотра видео вычислительной мощности этих МCU будет недостаточно. С простеньких примеров и начинаем.
Как повелось при изучении нового языка общения с компьютерными железяками, первая программа - “Hello, World!”.

Работа с текстовым дисплеем тривиальна, хотя получилось и не с первого раза — я ориентировался на документацию, в частности, на временные параметры, указанные производителем дисплея RayStar, но производитель себе несколько льстит, хотя это и не критично. После общения с несколькими графическими и текстовыми дисплеями было принято решение, что операции чтения из дисплея, включая признак занятости, это абсолютно ненужные операции - для каждого типа дисплея подбираются задержки, гарантирующие корректную работу. Для этого пришлось написать и отладочный макрос, позволяющий автоматически устанавливать точные задержки, вне зависимости от тактовой частоты микроконтроллера.

Парочка текстовых дисплеев и графический сенсорный дисплей DOGM-128e с интерфейсом SPI
Более того, вполне естественное решение — устроить промежуточный буфер во встроенной SRAM, равный размеру экранной области, и формировать изображения в нем, а операцию перезаписи в RAM дисплея организовать в обработчике прерывания по таймеру. Такая операция гораздо удобнее, так как запись одного символа в RAM дисплея требует около 40мкс, в то время как запись в SRAM, при тактовой частоте 8МГц, требует всего 2 такта, то есть 250нс. Таким образом, нет нужды и в прочих аппаратных особенностях, связанных со скроллингом, морганием и т.д., все просто и быстро реализуется программно, если в этом есть необходимость.
Большей частью такие преимущества проявляются в графических дисплеях с внутренним контроллером и RAM, так как общее пространство пикселей сегментируется по возможностям примененных контроллеров дисплея и часто требуется переустановка адреса страницы перед выводом пиксела.

Текстовые дисплеи на распространенных контроллерах имеют возможность запрограммировать 10 стандартных символов. Если ROM дисплея не содержит кириллицы, то получить полноценный русский шрифт будет тяжело.

Русский шрифт зашит в ROM. Сверху парочка ЦАП TDA8444, подключенных по интерфейсу I2C
А вот для корректировки начертания некоторых символов этого вполне хватит. Например, бросается в глаза буква «ц», буквы «в», «ь» и некоторые другие получили укороченный размер, можно подкорректировать и знаки препинания:

В нижней строке дисплея исправлены буквы «ц», «в», «ь», «ы» и запятая опущена на один пиксел вниз
Впрочем, это мелочи и все это делалось с тренировочной целью, так как в процессе моих экспериментов я ставил своей целью охватить максимально возможный объем функционала как микропроцессоров, так и тех устройств, которые с ними сопрягаются. Более практичным, в плане программирования дополнительных символов, может быть, к примеру, программирование показа уровней сигнала аудиоплеера по частотам, после обработки этого сигнала преобразованием Фурье.
Вот пример более полезного использования 4-х строчного текстового дисплея, для вывода содержимого 32 байт памяти (или регистров общего назначения), так как не всегда это удобно делать под отладчиком без дополнительного аппаратного обеспечения в условиях обработки внешних сигналов. В данном случае часть программы и текстовый дисплей как раз и являются таким дополнительным оборудованием.

(кликните по картинке для увеличения)
Следующим шагом, по горячим следам после статьи «Microlab Solo6C – сигналы управления», стала реализация этих самых сигналов управления на базе микроконтроллера Atiny2313, как одного из самых дешевых в семействе Atmel. Впрочем, он все равно явно дороже примененного китайцами MCU NSR2251, который стоит менее 1 юаня (0.15$), но у меня нет доступа ни к NSR2251, ни к документации по нему.

Вместо двухзнакового LED-дисплея использовался 4-х знаковый, что более практично, так как пришлось разрабатывать обработчик IR-сигналов по стандарту NEC, на фото как раз видны принятые от ПДУ Solo6C адрес 0х01 и команда 0х0d. Несмотря на работу от калиброванного внутреннего генератора тактовой частоты, управляющие импульсы для микросхемы регулировки громкостью и тембром не имеют провалов по длительности, как под руководством оригинального NSR2251.

NSR2251

Atiny2313
Неравномерности на верхнем рисунке могут быть вызваны тем, что разрешены вложенные прерывания. Например, более приоритетное прерывание по приему IR-сигнала, но оно не может быть чаще, чем через 562.5мкс. Может наложиться и мультиплексирование знаков дисплея, но тогда слишком затянуто. Хорошо заметно пять больших аномалий, которые, по логике, не могут быть отнесены на счет одного и того же вложенного прерывания, так что, чем еще занимается
процессор NSR2251, видимо, навсегда останется для меня загадкой. Ну и ладно, возвращаемся к нашей работе.
Вся программа занимает чуть более одного килобайта. Впрочем, до практических испытаний дело не дошло, так как, во первых, немножко надоело, а, во-вторых, и потребовалось расширить функционал — для сохранения текущих настроек и различных профилей темброблока требовалось наличие явного сигнала выключения — ведь не записывать же в EEPROM эти данные после каждого изменения! Это можно реализовать и с помощью имеющегося пульта, например, измеряя время непрерывного нажатия кнопки «Mute», если мы ее назначаем ответственной за включение-выключение. Скажем, непрерывное нажатие в течение 3 секунд включает или выключает устройство, при этом сам контроллер и цепи управления запитываются от отдельного источника. Сразу хочется идти дальше — встроить часы реального времени, тюнер, и т.д.
На тот момент эта идея меня не вдохновила. Но вот как уже пару недель я к ней вернулся. Так что, возможны варианты.
Для полноценных графических приложений (разумеется, в рамках производительности выбранных MCU), нужно использовать графические дисплеи.

Поскольку не планировалось (пока) приобретение дисплеев с размером экрана выше 128х64 точек, то для обработки графики разрабатывались программы (по алгоритмам Брезенхема) в 8-битной арифметике, что наложило некоторые ограничения, например, на размер окружностей.
Четвертинки по углам дисплея имеют максимальный радиус в 43 пиксела, после которого начинается уже некоторое искажение вида окружности. Впрочем, низкое разрешение 128х64 само по себе не подарок.
Без прямых линий, прямоугольников и вывода времени, формирование такой картинки в SRAM занимает примерно 9.5мс (при тактовой частоте MCU 8 МГц), со всем остальным — менее 12 мс. Учитывая, что запись одного байта в VRAM дисплея занимает около 6мкс, перезапись всего экранного буфера из SRAM в VRAM займет около 6 мс, что, с учетом 12 мс времени рисования, обеспечит вывод более 50 кадров в секунду.
Кстати, разработка собственных графических процедур и началась после того, как на сайте Arduino я увидел библиотеку на Си, которая гордится выводом аж в целых 6 fps. При мощности MCU в 1 MIPS/МГц это просто курам на смех.
Реализация алгоритма Брезенхема для вывода окружности не оптимизирована и использует вызов функции PlotXY, вычисляющей координаты каждого пиксела. Это не оптимально с точки зрения быстродействия, так как точки примыкают друг к другу и приращение координат (если есть) всегда выполняется на один пиксел. Для вывода отрезков (прямых и под произвольным углом) реализация алгоритма сделана с оптимизацией. Прямые горизонтальные линии рисуются (в буфер) быстрее всего — несколько миллионов точек в секунду.
Но высокий fps, достижимый при программировании на ассемблере, разбивается об инерционность недорогого дисплея. Для имеющихся у меня графических дисплеев Raystar с желтозеленой и RGB подсветкой, типовое время включения и выключения пиксела составляет 200мс, максимальное — 300!
Поэтому такие дисплеи не пригодны для вывода динамического изображения, ради примера я запрограммировал квадратик, двигающийся в левой половине экрана и отражающийся от его границ, при этом стабилизируется fps=30:


Тут и сказать в общем-то нечего. Абсолютный неуд, при любых скоростях, соответствующих плавному перемещению квадратика, вплоть до стробоскопического эффекта.
Для сравнения, вот «статичные» пикселы того же дисплея и той же голубой подсветкой (у него она RGB):

Ну и, за компанию, пикселы текстового негативного дисплея с голубой подсветкой RC2004A-BIW-CSX:

Проверим динамику и с аппаратным скроллингом. Исходная картинка:

Правая половина будет сдвигаться аппаратно, левая — программно. Результат при медленной скорости:

Программный кажется чуть поярче, но это, вероятно, неравномерность подсветки и влияние светочувствительности объектива, на глаз неравномерность выражена гораздо слабее. Контрольный забег без подсветки и чуть побыстрее:

Более ничего и не скажешь. В запасе есть еще один мониторчик, с SPI интерфейсом и сенсорным покрывалом, но он занят пока в другом проекте. Но в то, что он будет заметно лучше, верится с трудом. Это — мониторы для промышленной автоматики. Надо пробовать более быстродействующие дисплеи или вывод на стандартный VGA-монитор. Правда, придется поизвращаться, но на просторах инета такие вещи описаны, даже сделаны подсоединение ISA-интерфейса и работа со стандартными ISA видеокартами типа Trident9000 и некоторыми другими. Это тоже своего рода оверклокингский спорт — как выжать из устройства то, на что оно явно не рассчитано.
К слову, о графических дисплеях. Поскольку это тоже была моя первая встреча с ними, то первый приобретенный дисплей оказался без генератора отрицательного напряжения, о необходимости которого я даже и не подозревал. К моему удивлению и негодованию, устройства на макетной плате, многократно пересобранные и перепроверенные, как для полета в космос, не могли высветить не единой точки на дисплее. Контрастность тоже не регулировалась и массива пикселов не было видно. Только через позорно долгое время я выяснил причину.

Слева - дисплей без установленной IC 7660, хотя разводка под нее есть, на фото справа такая IC установлена
На «полноценных» графических дисплеях ставится микросхема — преобразователь DC/DC, генерирующая необходимое для дисплея отрицательное напряжение, которого нужно 4 вольта с хвостиком. Обычно используется микросхема типа LM7660. С ходу под рукой таковой не оказалось, и я решил сгенерировать отрицательное напряжение, выпрямив импульсное со специально выделенного вывода MCU. Но моя затея провалилась - так как я запитывал всю схему от USB, то итоговое напряжение питания проседало до 4.6-4.7В (не из-за генерации минуса, там ток мизерный), что в итоге давало, в лучшем случае, -3.22В. Изображение было не контрастным, хотя и различимым. Изменение частоты и параметров выпрямителя существенного эффекта не дали, приемлемый контраст появлялся только при -3.7..-4.2В. Нужно было запитывать схему от источника 5.5В или делать схему умножения. И то, и другое нецелесообразно, поэтому просто были куплены микросхемы 7660 в DIP корпусе. Для конкретных поделок правильнее купить их в планарном корпусе и распаять на плате дисплея, благо место есть и нужно еще всего два конденсатора, а для экспериментов как раз и DIP корпуса.
Разумеется, были проделаны манипуляции по многоканальным измерениям с использованием как АЦП, так и ЦАП преобразований, измерения температуры. Опробован и метод адресного расширения пространства под периферию. Шина данных у большинства 8-разрядных MCU чисто внутренняя. Так как число выводов ограничено, то, в некоторых случаях, их может просто не хватить. Например, только 4-х знаковый LED “съест” 12 выводов. А если нужна, например, матрица клавиш 4х4, требующая еще 8 выводов, и другая периферия? На MCU с внешней шиной (Atmega8515, Atmega128 и др.) это решается просто, а что делать на остальных? На самом деле, и для LED (вывод), и для клавиатуры (ввод), можно обойтись гораздо меньшим числом выводов, используя, соответственно, регистры последовательный вход-параллельный выход (74НС164) и параллельный вход-последовательный выход (74НС165). Для примера, вот реализация клавиатуры на шесть клавиш на 74НС165:

Блок клавиатуры
Одна микросхема рассчитана на восемь клавиш, но здесь собран эмулятор джойстика, так как не попалось такового, пригодного для макетирования, есть только в smd-корпусе. 74НС165 имеет выходы для каскадирования, так что количество клавиш не ограничено, как и число одновременно нажатых. Любое количество микросхем требует только трех выводов MCU, причем возможна и работа через SPI или USART. Конечно, если не ставится цель сделать подешевле, то для таких целей и получения большей функциональности можно использовать и отдельный микроконтроллер. В этом смысле, например, ассортимент многочисленных расширителей шины I2C от Philips, стоящих в несколько раз выше длстаточно продвинутых MCU, вообще не имеет ни экономического, ни технического смысла.
Но эти вещи довольно тривиальны (по крайней мере, для меня), а вот, с чем я впервые столкнулся, так это с бытовыми RF приемниками, передатчиками и трансиверами. Устройства ZigBee и BT, хоть и доступны по цене и наличию, но для первого раза показалось, что они отнимут относительно много времени на изучение и поэтому были отложены. А вот несколько приемников и передатчиков диапазона 868 Мгц, с дальностью связи в несколько сот метров (так и хочется назвать это набором начинающего террориста), были приобретены:

Вполне адекватная замена IR связи и проводным соединениям автоматики в пределах дома. Для интереса пока проверил только скорость передачи. На вход передатчика подавался меандр, сигнал на выходе приемника контролировался по осциллографу. Скважность начинает уходить от 50% в районе 4.5КГц и к 30КГц начинает твориться черти что с выпадением импульсов. Так что аудио-видео не потянет, но прочие потребности умного дома вполне обслужит. А при использовании протокола от 1Wireинтерфейса возможна организации по одному каналу полудуплексного обмена с необходимым числом устройств. Осталось подумать, как оптимально защититься от сигналов соседей, если и они интенсивно будут использовать подобные устройства, радиус действия ведь не маленький. Канал один, чем больше народу — тем меньше свободного эфира.
Разумеется, область применения MCU не ограничивается описанными случаями. Но для первого знакомства, наверное, достаточно.
А с разгоном у них хорошо. Наверное. Пока руки до этого не дошли, но сбоев в относительно длительной работе (пара суток) пары 20Мгц MCU с кристаллом 29.8МГц не было. Конечно, это не говорит об их полной стабильности, тем более есть несколько хитрых внутренних увязок по частотам, но это показывает, что такая возможность есть. PLL-ки с подходящим диапазоном у меня нет, но есть кварцы на 40 и 50МГц, в smd исполнении. Так что, когда судьба сподвигнет на припайку двух ножек к каждому резонатору, обязательно проверим поведение MCU на этих частотах. Пока условно засчитаем, что рубеж 30МГц они взяли.
Честно говоря, даже не знаю — нужны ли детальные описания моей борьбы с микроконтроллерами, в частности — концептуальный подход по выбору элементной базы и схемотехническим решениям, подходы и приемы программирования на ассемблере для AVR, работа с препроцессором и макросами, работа с многоразрядными 7-сегментными индикаторами, текстовыми и графическими дисплеями, реализация алгоритма Брезенхема для построения графических примитивов, спрайтовая анимация, часы, периферия I2С, SPI, etc..
Если интерес к таким проблемам есть — задавайте вопросы в теме обсуждения статьи.

Комментарии, вопросы и предложения здесь.
zauropod,
специально для www.overclockers.ru
август 2009 года
Лента материалов
Соблюдение Правил конференции строго обязательно!
Флуд, флейм и оффтоп преследуются по всей строгости закона!
Комментарии, содержащие оскорбления, нецензурные выражения (в т.ч. замаскированный мат), экстремистские высказывания, рекламу и спам, удаляются независимо от содержимого, а к их авторам могут применяться меры вплоть до запрета написания комментариев и, в случае написания комментария через социальные сети, жалобы в администрацию данной сети.
Сейчас обсуждают