
- •Поехали!
- •Поговори-ка ты со мной..
- •Что то с памятью моей стало память.
- •Пример.
- •Итак, будем удивлять! Для начала необходимо спаять схему управления нагрузкой на 220 вольт.
- •Теперь надо научиться передавать данные через com-порт.
- •Программа для получения текстовых сообщений.
- •Итак. По порядку.
- •Ураа! склад!!!
слито с avr.ru/
ВВЕДЕНИЕ
я выключаю телевизор, я пишу тебе письмо, о том что больше не могу смотреть на дерьмо.
ДЛЯ ЧЕГО ЭТО НУЖНО.
Если нужно запрограммировать ведра, чтобы сами воду в дом таскали, Емеля-дурак пользуется щучьим велением. на то он и дурак. А реальные пацаны используют AVR.
Когда нужно научить кусок железа думать и подключаться к компьютеру, вам приходится решать задачу: делать это самому или попросить знающих людей. Ответ прост: для разовой задачи удобнее найти толкового программиста микроконтроллеров. Но, если планов ваших громадье, то лучше разобраться в деле самому.
Однако не всегда это просто само по себе. Профессионалы пишущие книги на эту тему часто забывают о принципе постепенности изложения материала, опуская "очевидное" и "само собой разумеющееся". в результате, изучив кучу всякого заумного бреда, собираешь простенькую схему, а она не работает. от такой неудачи не то что руки.. паяльник может опустится.
Для того, чтобы избежать подобной ситуации мы будем вводить новые понятия постепенно, по мере накопления опыта, расчитывая в первую очередь на "новичка", не занимавшегося ранее микроконтроллерами. по этому для начала хватит самых минимальных знаний об электронике и программировании. Причем, сперва мы будем "запускать" схему, а уже потом рассматривать как она работает и творчески издеваться над ней. Начинем с простейшей задачи - "дергать" в определенном порядке "ногами" микросхемы, и все более усложняя примеры и дойдем до вполне серьезных и "взрослых" разработок.
А уж подключить Даласовский термометр к компьютеру чтобы вывести информацию на дисплей, подключить индикатор, считать информацию с домофонного ключа или метки, и много других полезностей и вкусностей будет для вас плевым делом.
ЧТО ДЛЯ ЭТОГО НУЖНО.
в первую очередь нам понадобятся несколько учебных чипов, хорошо бы также иметь макетную плату с набором перемычек, пару светодиодов, резисторов на 1 ком, кнопку и блок питания. также необходим программатор. из софта необходим ассемблер и программа для работы с программатором.
несмотря на кажущуюся запарочность данного списка все детали в нем легко "доставаемы". так например, можно купить программатор в собранном виде, можно спаять изодного разъема для принтера и простой ТТЛ микросхемы, а можно купить как набор и/или собрать самому.
Блок питания - любой китайский для сотового телефона. можно конечно питать свою конструкцию от USB порта.. но опасно.
Чипы можно заказать по интернету, а для жителей крупных городов - купить в магазине радиодеталей. там же можно купить светодиоды кнопки и резисторы. особо хочу обратить внимание на макетную плату. не пожалейте денег - купите. экономия времени просто потрясающая.
ЕЩЕ ОДИН СОВЕТ:
Без паники! несмотря на кажущуюся неподъемность темы язык ассемблер чем-то очень похож на язык программируемых микрокалькуляторов. Так что если вы когда-то писали программы для МК-61, МК-52 или им подобным, то программирование на ассемблере AVR освоите легко.
Схемотехника тоже не слишком сложна. знаний по физике за курс средней школы хватит. главное не забыть что ток измеряется амперметром, а напряжение напряжометром.
Поехали!
Ну, нет у меня пока никакого желания вдаваться в глубокомысленные рассуждения об отличиях Гарвардской и фон-неймановской архитектуры. Хочется просто ощутить что ОНО работает. Ну так извольте-с. На этом этапе мы будем просто учиться собирать рабочие схемы. Берем микросхему ATtiny2313 (это улучшенная AT90S2313). Скачиваем файл с прошивкой, собираем схему и пробуем запустить.
Схема которую мы должны собрать очень простая. Кнопка, микросхема, источник питания, светодиод и резистор. Все. Задача - зажечь светодиод, когда мы нажимаем на кнопку.
Для того чтобы диод засветился надо чтобы через него потек ток. То есть необходимо, чтобы на выходе PB5 микросхемы был логический ноль (который физически означает подключение к шине «земля»). Нажатие кнопки приводит к подключению входа к «земле» и следовательно установке на нем логического ноля.
Следовательно - все что делает программа - это считывание логического уровня со входа PD5 и трансляция его на выход PB5.
Итак.
1. Берем программатор и программу для работы с ним.
Программатор подробно описан в статье «простой программатор», а программу Avr-Osp II by Mike Henning можно также скачать с сайта. Тут - подробное описание. Настройка сводится к выбору Порта и скорости и типа программатора (AVR911) на вкладке Configurate.
2. Скачиваем прошивку для этого микроконтроллера.
Файл sbs_01.hex содержит шестнадцатеричный дамп программы которая инициализирует «ноги» чипа, а затем в бесконечном цикле передает значения считанные со входов на выходы.
3. Убедимся что чип сконфигурирован правильно.
Необходимо вставить чип в программатор соблюдая цоколевку. Затем на вкладке Program на панели Device нажать кнопку AutoDetect, и убедится, что чип распознан правильно.. Перейдя на вкладку FuseBits считываем конфигурацию с помощью кнопки Read и проверяем, установлен ли признак работы от внутреннего генератора (для упрощения схемы мы выкинули кварцевый резонатор). Обычно свежекупленные микросхемы сразу имеют включенный признак Int RC Osc. если это не так, то устанавливаем этот признак и нажимаем кнопку Program
4. «Заливаем» в чип программу.
Снова переходим на вкладку Program и указав на файл sbs_01.hex на вкладке FLASH нажимаем кнопку Program.. если установленны все флажки на панели Auto program settings то программа сама выполнит стирание чипа, заливку программы и проверку правильности только что записанной информации. Обовсех своих действиях программа сообщает в нижнем окне. Сообщение Equal! Говорит об успешном завершении процесса прошивки.
5. Собираем на макетной плате вышеприведенную схему.
В принципиальной схеме даны номера ножек и номинал (приблизительный) резистора. Цоколевка ножек микросхемы начинается от ключа в обратную ходу часовой стрелки сторону. Если вы не смогли собрать эту схему, то лучше вообще обходить стороной электроприборы.
6. Подключаем к источнику питания
Проще всего взять источник питания для мобильного телефона. Обрезав телефонный разъем и проверив тестером полярность (или на глаз черный - земля, красный - +5V) подключаем к нашему устройству.
7. Нажимаем кнопку...
... и пыримся на горящий светодиод.
Данная последовательность действий позволяет убедится в собственных силах, а главное, убедится в работоспособности оборудования. Чтобы в дальнейшем не было сомнений - что глючит, железо или софт.
Теперь вы готовы к следующему этапу - освоению языка assembler и программы AVRStudio.
УЛИЧНАЯ МАГИЯ.
Теперь необходимо научится компилировать программы, чтобы получить файл прошивки.
Первое что необходимо сделать – это скачать программу AvrStudio и установить ее на свой компьютер. Далее необходимо создать новый проект. В меню нужно открыть Project – new project. Затем на открывшемся диалоге выбрать создание проекта на ассемблере, ввести имя и тд.
В следующем окне нужно выбрать тип микросхемы для которой мы пишем, и платформу на которой отлаживаемся.
В результате откроется окно среды разработки. В окошко файла исходного кода мы копируем ниже приведенный пример. И жмем в меню на Build или просто на кнопкуF7.
пример программы:
;======================================================================= ;Autor: MadMayDay 2008 ;Project: StepByStep ;Name: LED ;======================================================================= .device AT90S2313 .include "2313def.inc" .def SlopReg=R16 ;======================================================================= Start: rjmp Init; ;---------------------------------------------------------- ;устанавливаем часть ног микросхемы в состояние "выход", ;и часть в состояние "вход" ;входы 02,03,06,07,08,09,11 ;выходы 12,13,14,15,16,17,18,19 Init: ldi SlopReg,0b11111111 ; грузим признак выхода out DDRB,SlopReg ; в регистр управления ; портом "B" ldi SlopReg,0b00000000 ; грузим признак входа out DDRD,SlopReg ; в регистр упр. портом "D" ldi SlopReg,0b11111111 ; грузим признак "активности" out PortD,SlopReg ; в регистр входа ;---------------------------------------------------------- ; просто тупо перекладываем все из D в B. Begin: in SlopReg,PinD out PortB,SlopReg; rjmp Begin; End: ;====================================================================== |
Этот текст и откомпилированный файл можно скачать здесь или просто выделить на экране и скопировать в окно ввода текста.
В нижнем окне должно высветится сообщение о нулевом количестве ошибок. В каталоге программы должен появится файл с именем как у нашего проекта а расширением .HEX это собственно и есть дамп программы который мы закачиваем в память чипа.
Теперь когда мы реально увидели что все работает, разберемся что, а главное как работает.
НОГУ СВЕЛО!
Теперь разберем подробно программу, которая только что была залита в чип. Написана на языке ассемблера (язык ассемблера схож с языком для программируемых микрокалькуляторов). В отличие от языков высокого уровня, в ассемблере нет конструкций типа присвоение, условные операторы, циклы и тому подобное. Вся программа состоит из последовательности машинных команд и блоков данных. А уже сами машинные команды могут быть командами пересылки, перехода по условию и т.д. Программисту на языке ассемблера самому приходится заботиться о распределении памяти и использовании регистров.
Выглядит оно вот так
;======================================================================= ;Autor: MadMayDay 2008 ;Project: StepByStep ;Name: LED ;======================================================================= .device AT90S2313 .include "2313def.inc" .def SlopReg=R16 ;======================================================================= Start: rjmp Init; ;---------------------------------------------------------- ;устанавливаем часть ног микросхемы в состояние "выход", ;и часть в состояние "вход" ;входы 02,03,06,07,08,09,11 ;выходы 12,13,14,15,16,17,18,19 Init: ldi SlopReg,0b11111111 ; грузим признак выхода out DDRB,SlopReg ; в регистр управления ; портом "B" ldi SlopReg,0b00000000 ; грузим признак входа out DDRD,SlopReg ; в регистр упр. портом "D" ldi SlopReg,0b11111111 ; грузим признак "активности" out PortD,SlopReg ; в регистр входа ;---------------------------------------------------------- ; просто тупо перекладываем все из D в B. Begin: in SlopReg,PinD out PortB,SlopReg; rjmp Begin; End: ;====================================================================== |
Начнем разбирать пример по строчкам.
Строчки, начинающиеся с точки с запятой, являются комментариями и компилятором не учитываются. Строки, начинающиеся с точки, являются директивами компилятора, и заставляют компилятор выполнять определенные действия. Остальные рассматриваются компилятором как мнемоники (имена) машинных команд микроконтроллера. Команды состоят из имени и операндов. Операндами могут являться регистры, или константы. Кроме того существуют «метки» оканчивающиеся на двоеточие.
Разберем приведенный выше пример. Сперва идут директивы компилятора.
.device AT90S2313 - указывает компилятору, для какого типа процессора компилировать программу.
.include "2313def.inc" – указывает компилятору включить в тело программы дополнительный файл.
.def SlopReg=R16 – указывает компилятору, что шестнадцатый рабочий регистр мы будем называть SlopReg.
После идет блок команд настраивающих «переферию» ядра микроконтроллера. Затем идет основной цикл
Ldi - команда загрузки константы в рабочий регистр.
Out – команда загрузки значения из рабочего регистра в порт.
In – команда загрузки значения из порта в рабочий регистр.
Rjmp – команда перехода по указанному адресу.
Разберем работу микропроцессора под управлением данной программы:
Если образно представить чип как некую фирму, то корпус – это здание фирмы. Процессор – это директор. Еще в этом здании существуют сотрудники – это периферия процессора. (ну а мы скромненько так – учредители всего этого безобразия)
Микропроцессор имеет несколько рабочих регистров (регистров общего назначения). Под рабочими регистрами мы подразумеваем определенные области памяти находящиеся внутри микропроцессора. Более просто можно представить тридцать два (или больше) пустых папки поставленных одна за другой и пронумерованных (R1, R2…R16). Кроме процессора (директора) никакие устройства не имеют к ним доступ.
Кроме регистров общего назначения чип имеет «на борту» регистры специального назначения или «порты». С их помощью процессор управляет всей «периферией», которая находится в чипе. Они не являются собственностью процессора. Если снова образно представить чип как фирму, то директор раздает служащим задания через окошки в конторках. Эти «окошки» и есть регистры управления. Каждый служащий – это периферийное устройство, которое умеет делать только определенные действия, понимает определенные команды и закреплено за своим «окошком». Задача «директора» организовать совместную работу служащих. Он не знает какой «человек» сидит за окошком, и каким образом он выполняет порученное задание. Задача директора лишь дать нужные данные в нужное окошко.
То есть, уясним главное – у процессора НЕТ отдельных команд для доступа к определенным «периферийным» устройствам. Он не знает их «фамилии». Вся периферияуправляется с помощью записываемых в соответствующие регистры управления данных. Регистры управления, как и рабочие регистры, пронумерованы. Однако, для удобства использования в программе у них есть еще и имена. Компилятор, обрабатывая программу, заменяет эти имена на соответствующие им номера.
«Ноги» (выводы) чипа – это тоже «периферия», в простейшем случае они разделены на несколько групп. Каждая группа управляется портами, с помощью которых можно установить режим работы – прием или передачу данных. Возвращаясь к нашей ассоциации со зданием – ноги чипа это входы и выходы. В нашем здании есть несколько вестибюлей (групп выводов). Каждый вестибюль имеет 8 таких дверей. Они могут быть либо закрыты, либо работать вход, либо на выход.
В нашем случае мы используем «вестибюль» (физический порт) «B» и «D». В данном случае речь идет об устройстве, управляющем выводами 2,3,6,7,8,9,11 (порт B) и 12,13,14,15,16,17,18,19 (порт D). У каждого из этих устройств есть несколько регистров управления. Один регистр отвечает за направление DDRX(DataDirectionRegistr). Другой регистр отвечает за состояние выводов PinX. Этот регистр предназначен для чтения и служит лишь индикатором (частая ошибка новичков – писать в этот регистр. Но это тоже самое, что пытаться поднять напряжение в сети передвигая стрелку вольтметра). Третий регистр PortX используется в зависимости от направления. Когда ножка чипа сконфигурирована на ввод регистр PortX управляет «подтяжкой» (образно выражаясь доводчиком, пружиной двери) если не указать применение «подтяжки» нога чипа, оставленная в «воздухе» (то есть не присоединенный ни к земле, ни к питанию) будет «плавать» между нулем и единицей (как дверь болтается на ветру). Когда нога сконфигурирована на вывод – регистр PortX управляет её состоянием – ноль или единица.
Первыми двумя командами мы конфигурируем порт "B" так все его ножки становятся выходами. Каждому биту соответствует своя ножка. Когда бит устанавливается в единицу - ножка конфигурируется как выход. Когда в ноль - соответственно как вход.
ldi SlopReg,0b11111111 ; грузим признак выхода
out DDRB,SlopReg ; в регистр управления портом "B"
следующие две команды конфигурируют порт "D" как вход.
ldi SlopReg,0b00000000 ; грузим признак входа
out DDRD,SlopReg ; в регистр упр. портом "D"
еще две команды устанавливают «подтяжку» к единице (высокий уровень) ножек порта "D"
ldi SlopReg,0b11111111 ; грузим признак "активности"
out PortD,SlopReg ; в регистр входа
Обратите внимание, что мы не можем напрямую «залить» константу в регистр управления. Это можно сделать только через рабочий регистр. Объясняется это тем, микросхемы AVR имеют так называемую RISC архитектуру ядра.
Что такое RISC архитектура и чем она отличается от того процессора, что стоит в наших компьютерах (CISC)?. Образно можно сравнить их как жонглера(RISC) и фокусника(CISC). Фокусник может переместить любой мячик в любое место, да и вообще превратить его во что угодно, однако он может оперировать всего несколькими мячиками и не очень быстро. Жонглер за один момент может переместить мячик только недалеко от себя, и то, только тот, который держит в руках, однако делает это очень быстро и может удержать в руках гораздо больше шариков, чем фокусник. Вот, в общем, и все концептуальные различия.
Теперь все что нужно сделать нашей программе – это переложить значения, полученные из порта “D” в порт “B”. Опять же через рабочий регистр..
Begin: in SlopReg,PinD
out PortB,SlopReg;
и повторить это пока не наступит маленький конец света в масштабе одной микросхемы.
rjmp Begin;
вот в общем то и все. Программа предельно проста – берет уровни с одних ножек и выставляет такие-же на соответствующих.
ТВОРЧЕСКИЕ ИЗДЕВАТЕЛЬСТВА.
Теперь попробуем немного изменить схему и программу.
Для начала натыкаем светодиодов, да побольше. Так, чтобы получилась световая дорожка.. Теперь можно развлекаться созданием световых эффектов. Подаешь на ножку нолик– светодиод светится, подаешь еденичку – нет. Инструкция по сборке схемы проста: соединяем со светодиодами ножки чипа с 12дцатой по 19ую также как на предыдущей схеме была соединена только 17ая нога чипа.
Теперь пора поизмываться над программой. Мы будем создавать световой эффект – луч бластера. Для этого необходимо создать некий стек, типа «очередь» или по науке FiFo, ставить в очередь состояние кнопки, и потихоньку сдвигать эту очередь, отображая ее на «экран» из восьми светодиодов.
Секция инициализации точно такая же как у предыдущей программы.
Стек мы сформируем из регистра R18 и назовем его ViewReg. Принцип очереди будем формировать, сдвигая содержимое регистра влево, то есть от младших адресов к старшим. В начале программы мы «обнуляем» содержимое стека, записывая в него единицы командой ldi. (именно единицы не отображаются на нашем «крутом» восьмипиксельном мониторе).
Далее начинается бесконечный цикл, вначале которого командой out мы отображаем содержимое стека ViewReg в порт PortB.
Основная проблема в том, что чип у нас слишком быстрый. То есть, если не обеспечить задержку, то светодиоды будут мигать с такой частотой что мы даже и не заметим что что-то изменяется. По этому мы должны чем-то занять микропроцессор
ldi Xh,0x7f
ldi Xl,0xff
Delay: sbiw Xh:Xl,1
brne delay
Этот кусок кода обеспечивает занятость процессора обратным отсчетом от 0x7FFF до ноля. (Эй, кто сказал, что не понял, что это за число такое? В Бобруйск, животное! учить олбанские системы счисления!). Смысл в том что некоторые из рабочих регистров процессор может обрабатывать парами., тоесть как машинное слово в 2 байта. У таких регистров есть специальные имена: X, Y, Z. Соответственно имена пар регистров входящих в эти «составные» регистры Xh:Xl, Yh:Yl, Zh:Zl. Мы используем регистровую пару Х. Командами ldi мы загружаем в регистровую пару число 0x7FFF. Затем командой sbiw мы вычитаем единицу из этой пары. А команда brneосуществляет переход если результат предыдущей операции небыл равен нолю. Таким образом, пока в регистровой паре не будет значение 0, процессор будет «крутится» в пустом цикле, обеспечивая задержку.
После задержки мы опрашиваем пятый вход порта D (это 9 ножка чипа) и запоминаем его состояние командой bst. После чего сдвигаем стек командой lsl. Далее, cпомощью команды bld заполняем нулевой элемент стека запомненным состоянием пятого входа порта D
После чего программа выполняет безусловный переход на начало цикла, и снова отображает содержимое стека.
;========================================================== ;Autor: MadMayDay 2008 ;Project: StepByStep ;Name: LED ;========================================================== .device AT90S2313 .include "2313def.inc" .def SlopReg=R16 .def ViewReg=R18 ;========================================================== Start: rjmp Init; ;---------------------------------------------------------- ;устанавливаем часть ног микросхемы в состояние "выход", ;и часть в состояние "вход" ;входы 02,03,06,07,08,09,11 ;выходы 12,13,14,15,16,17,18,19 Init: ldi SlopReg,0b11111111 ; грузим признак выхода out DDRB,SlopReg ; в регистр управления ; портом "B" ldi SlopReg,0b00000000 ; грузим признак входа out DDRD,SlopReg ; в регистр упр. портом "D" ldi SlopReg,0b11111111 ; грузим признак "активности" out PortD,SlopReg ; в регистр входа ;---------------------------------------------------------- ; заталкиваем данные из регистра D в стек FIFO8 ; отображаем состояние стека на «монитор» регистра B ldi ViewReg,0xff ; формируем начальное состояние стека Begin: out PortB,ViewReg ;отображаем состояние стека на «экране» ldi Xh,0x7f ;формируем задержку циклом ldi Xl,0xff Delay: sbiw Xh:Xl,1 brne delay in SlopReg,PinD ;считываем показания кнопок bst SlopReg,5 ;запоминаем состояние кнопки #5 lsl ViewReg ;сдвигаем стек. bld ViewReg,0 ;задвигаем в стек считанное состояние rjmp Begin ; и снова здорова. End: ;========================================================== |
Программу и прошивку можно скачать с сайта или просто скопировать с экрана.
После компиляции и прошивки этой программы мы можем нажимать на кнопку, и наблюдать световые эффекты .