Примеры на Си для микроконтроллеров Atmel AVR

Подключение avr микроконтроллера к компьютеру

Данные статьи посвящены программированию микроконтроллеров AVR фирмы Atmel на языках С и С++. AVR – это, пожалуй, самое распространенное семейство микроконтроллеров.

Итак, что вообще такое микроконтроллер (далее МК)? Это, условно говоря, маленький компьютер, размещенный в одной интегральной микросхеме. У него есть процессор (арифметическо-логическое устройство, или АЛУ), flash-память, EEPROM-память, множество регистров, порты ввода-вывода, а также дополнительные «навороты», такие как таймеры, счетчики, компараторы, USARTы и т. п. Микроконтроллер после подачи питания загружается и начинает выполнять программу, записанную в его flash-памяти. При этом он может через порты ввода/вывода управлять самыми разнообразными внешними устройствами.

Что же это означает? Это значит, что в МК можно реализовать любую логическую схему, которая будет выполнять определенные функции. Это значит, что МК – микросхема, внутреннее содержимое которой, фактически, мы создаем сами. Что позволяет, купив несколько совершенно одинаковых МК, собрать на них совершенно разные схемы и устройства. Если вам захочется внести какие-либо изменения в работу электронного устройства, то не нужно будет использовать паяльник, достаточно будет лишь перепрограммировать МК. При этом не нужно даже вынимать его из вашего дивайса, если вы используете AVR, т. к. эти МК поддерживают внутрисхемное программирование. Таким образом, микроконтроллеры ликвидируют разрыв между программированием и электроникой.

AVR – это 8-битные микроконтроллеры, т. е. их АЛУ может за один такт выполнять простейшие операции только с 8-ми битными числами. Теперь пора поговорить о том, какой МК мы будем использовать. Я работаю с МК ATMega16. Он очень распространенный и приобрести его можно практически в любом магазине радиодеталей где-то за 100 руб. Если вы его не найдете – тогда можно купить любой другой МК серии MEGA, но в этом случае придется искать к нему документацию, т. к. одни и те же «ножки» разных МК могут выполнять разные функции, и, подключив, казалось бы, правильно все выводы, вы, может быть, получите рабочее устройство, а, может быть, лишь облако вонючего дыма. При покупке ATMega16 проверьте, чтобы он был в большом 40-ножечном DIP-корпусе, а также купите к нему панельку, в которую его можно будет вставить. Для работы с ним потребуются также дополнительные устройства: светодиоды, кнопки, разъемы и т. п..

ATMega16 обладает очень большим количеством самых разнообразных функций. Вот некоторые его характеристики:

  • Максимальная тактовая частота – 16 МГц (8 МГц для ATMega16L)
  • Большинство команд выполняются за один такт
  • 32 8-битных рабочих регистра
  • 4 полноценных 8-битных порта ввода/вывода
  • два 8-битных таймера/счетчика и один 16-битный
  • 10-разрядный аналогово-цифровой преобразователь (АЦП)
  • внутренний тактовый генератор на 1 МГц
  • аналоговый компаратор
  • интерфейсы SPI, I2C, TWI, RS-232, JTAG
  • внутрисхемное программирование и самопрограммирование
  • модуль широтно-импульсной модуляции (ШИМ)

Полные характеристики этого устройства, а также инструкции по их применению можно найти в справочнике (Datasheetе) к этому МК. Правда, он на английском языке. Если вы знаете английский, то обязательно скачайте этот Datasheet, в нем много полезного.

Приступим, наконец, к делу. Я рекомендую изготовить для микроконтроллера специальную макетно-отладочную плату, на которой можно будет без паяльника (или почти без него) собрать любую электрическую схему с микроконтроллером. Использование такой платы значительно облегчит работу с МК и ускорит процесс изучения его программирования. Выглядит это так:

Что для этого понадобится?

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

Для соединения элементов схемы очень удобно использовать шлейфы, на концах которых установлены разъемы. Эти разъемы надеваются на «ножки», торчащие рядом с каждым портом МК. Микроконтроллер следует устанавливать в панельку, а не припаивать к плате, иначе его очень трудно будет вынуть в случае, если вы его случайно сожжете. Ниже приведена цоколевка МК ATMEGA16:

Поясним, какие ножки нас сейчас интересуют.

  • VCC – сюда подается питание (4,5 – 5,5 В) от стабилизированного источника
  • GND – земля
  • RESET – сброс (при низком уровне напряжения)
  • XTAL1, XTAL2 – сюда подключается кварцевый резонатор
  • PA, PB, PC, PD – порты ввода/вывода (A, B, C и D соответственно).

В качестве источника питания можно использовать все, что выдает 7-11 В постоянного тока. Для стабильной работы МК нужно стабилизированное питание. В качестве стабилизатора можно использовать микросхемы серии 7805. Это линейные интегральные стабилизаторы, на вход которых подают 7-11 В постоянного нестабилизированного тока, а на выходе получают 5 В стабилизированного. Перед 7805 и после него нужно поставить фильтрующие конденсаторы (электролитические для фильтрации помех низких частот и керамические для высоких). Если не удается найти стабилизатор, то можно в качестве источника питания использовать батарейку на 4,5 В. От нее МК нужно питать напрямую.

Ниже приведу схему подключения МК:

Давайте теперь разберемся, что здесь для чего.

BQ1 – это кварцевый резонатор, задающий рабочую частоту МК. Можно поставить любой до 16 МГц, но, поскольку мы планируем работать в будущем и с COM-портом, то рекомендую использовать резонаторы на следующие частоты: 14,7456 МГц, 11,0592 МГц, 7,3725 МГц, 3,6864 МГц или 1,8432 МГц (позже станет ясно, почему). Я использовал 11,0592 МГц. Понятное дело, что чем больше частота, тем выше и скорость работы устройства.

R1 – подтягивающий резистор, который поддерживает напряжение 5 В на входе RESET. Низкий уровень напряжения на этом входе означает сброс. После сброса МК загружается (10 – 15 мс) и начинает выполнять программу заново. Поскольку это высокоомный вход, то нельзя оставлять его «болтающимся в воздухе» — небольшая наводка на нем приведет к непредвиденному сбросу МК. Именно для этого и нужен R1. Для надежности рекомендую также установить конденсатор С6 (не более 20 мкФ).

SB1 – кнопка сброса.

Кварцевый резонатор и фильтрующий конденсатор C3 должны располагаться как можно ближе к МК (не далее 5-7 см), т. к. иначе могут возникать наводки в проводах, приводящие к сбоям в работе МК.

Синим прямоугольником на схеме обведен собственно программатор. Его удобно выполнить в виде провода, один конец которого втыкается в LPT порт, а другой – в некий разъем рядом с МК. Провод не должен быть чрезмерно длинным. Если возникнут проблемы с этим кабелем (обычно не возникают, но всякое бывает) то придется спаять адаптер Altera ByteBlaster. О том, как это сделать, написано в описании к программатору AVReal.

Теперь, когда разобрались с железом, пора перейти к программному обеспечению.

Для программирования AVR есть несколько сред разработки. Во-первых, это AVR Studio – официальная система программирования от Atmel. Она позволяет писать на ассемблере и отлаживать программы, написанные на ассемблере, С и С++. IAR – это коммерческая система программирования на C, С++ и ассемблере. WinAVR – компилятор с открытыми исходниками. AtmanAVR – система программирования для AVR с интерфейсом, почти «один в один» таким же, как у Visual C++ 6. AtmanAVR также позволяет отлаживать программы и содержит множество вспомогательных функций, облегчающих написание кода. Эта система программирования коммерческая, но, согласно лицензии, ее можно в течение месяца использовать «нахаляву».

Я предлагаю начать работу с IAR как с наиболее «прозрачной» средой разработки. В IAR проект целиком создается «ручками», соответственно, сделав несколько проектов, вы уже будете четко знать, что означает каждая строчка кода и что будет, если ее изменить. При работе же с AtmanAVR придется либо пользоваться предварительно созданным шаблоном, который очень громоздкий и трудный для понимания для человека, не имеющего опыта, либо иметь множество проблем с заголовочными файлами при сборке проекта «с нуля». Разобравшись с IAR, мы впоследствии рассмотрим другие компиляторы.

Итак, для начала раздобудьте IAR. Он очень распространен и его нахождение не должно быть проблемой. Скачав где-либо IAR 3.20, устанавливаем компилятор / рабочую среду, и запускаем его. После этого можно начинать работу.

Запустив IAR, выбираем file / new / workspace, выбираем путь к нашему проекту и создаем для него папку и даем имя, например, «Prog1». Теперь создаем проект: Project / Create new project… Назовем его также – «Prog1». Щелкаем правой кнопкой мыши на заголовке проекта в дереве проектов и выбираем «Options»

Здесь будем настраивать компилятор под конкретный МК. Во-первых, нужно выбрать на вкладке Target тип процессора ATMega16, на вкладке Library Configuration установить галочку Enable bit definitions in I/O-include files (чтобы можно было использовать в коде программы имена битов различных регистров МК), там же выбрать тип библиотеки С/ЕС++. В категории ICCAVR нужно на вкладке Language установить галочку Enable multibyte support, а на вкладке Optimization выключить оптимизацию (иначе она испортит нашу первую программу).

Далее выбираем категорию XLINK. Здесь нужно определить формат откомпилированного файла. Поскольку сейчас мы задаем опции для режима отладки (Debug), о чем написано в заголовке, то на выходе нужно получить отладочный файл. Позже мы его откроем в AVR Studio. Для этого нужно выбрать расширение .cof, а тип файла – ubrof 7.

Теперь нажимаем ОК, после чего меняем Debug на Release.

Снова заходим в Options, где все параметры, кроме XLINK, выставляем те же. В XLINK меняем расширение на .hex, а формат файла на intel-standart.

Вот и все. Теперь можно приступать к написанию первой программы. Создаем новый Source/text и набираем в нем следующий код:

Файл «iom16.h» находится в папке (C:Program Files)IAR SystemsEmbedded Workbench 3.2avrinc. Если вы используете другой МК, например, ATMega64, то выбирайте файл «iom64.h». В этих заголовочных файлах хранится информация о МК: имена регистров, битов в регистрах, определены имена прерываний. Каждая отдельная «ножка» порта A, B, C или D может работать либо как вход, либо как выход. Это определяется регистрами Data Direction Register (DDR). 1 делает «ножку» выходом, 0 – входом. Таким образом, выставив, например, DDRA = 13, мы делаем выходами «ножки» PB0, PB2, PB3, остальные – входы, т.к. 13 в двоичном коде будет 00001101.

PORTB – это регистр, в котором определяется состояние «ножек» порта. Записав туда 0, мы выставляем на всех выходах напряжение 0 В. Далее идет бесконечный цикл. При программировании МК всегда делают бесконечный цикл, в котором МК выполняет какое-либо действие, пока его не сбросят или пока не произойдет прерывание. В этом цикле пишут как бы «фоновый код», который МК выполняет в самую последнюю очередь. Это может быть, например, вывод информации на дисплей. В нашем же случае увеличивается содержимое регистра PORTB до тех пор, пока он не заполнится. После этого все начинается сначала. Наконец, цикл for на десять тысяч тактов. Он нужен для формирования видимой задержки в переключении состояния порта В.

Если не выключить оптимизацию, то компилятор сочтет этот цикл бесполезной тратой времени и выкинет его из программы!

Теперь сохраняем этот файл в папке с проектом как Prog1.c, копируем в папку с проектом файл iom16.h, выбираем Project/Add Files и добавляем «iom16.h» и «Prog1.c». Выбираем Release, нажимаем F7, программа компилируется и должно появиться сообщение:

Total number of errors: 0
Total number of warnings: 0

Приведу фотографию своего программатора:

Скачиваем программатор AVReal. Копируем его (AVReal32.exe) в папку Release/exe, где должен лежать файл Prog1.hex. Подаем питание на МК, подключаем кабель-программатор. Открываем Far Manager (в нем наиболее удобно прошивать МК), заходим в эту папку, нажимаем Ctrl+O. Поскольку у нас совершенно новый МК, то набиваем

avreal32.exe +MEGA16 -o11.0592MHZ -p1 -fblev=0,jtagen=1,cksel=F,sut=1 –w

Не забудьте правильно указать частоту, если используете не 11059200 Гц! При этом в МК прошиваются т.н. fuses – регистры, управляющие его работой (использование внутреннего генератора, Jtag и т.п.). После этого он готов к приему первой программы. Программатору в качестве параметров передают используемый LPT-порт, частоту, имя файла и другие (все они перечислены в описании к AVReal). Набираем:

Avreal32.exe +Mega16 -o11.0592MHz -p1 -e -w -az -% Prog1.hex

В случае правильного подключения программатор сообщит об успешном программировании. Нет гарантии, что это получится с первого раза (при первом вызове программы). У меня самого бывает программируется со второго раза. Возможно, LPT-порт глючный или возникают наводки в кабеле. При возникновении проблем тщательно проверьте свой кабель. По своему опыту знаю, что 60% неисправностей связаны с отсутствием контакта в нужном месте, 20% — с наличием в ненужном и еще 15% — с ошибочной пайкой не того не к тому. Если ничего не получится, читайте описание к программатору, попробуйте собрать Byte Blaster.

Предположим, у вас все работает. Если теперь подключить к порту В МК восемь светодиодов (делайте это в выключенном состоянии МК, и желательно последовательно со светодиодами включить резисторы в 300-400 Ом) и подать питание, то произойдет маленькое чудо – по ним побежит «волна»!

Примеры на Си для микроконтроллеров Atmel AVR

Здесь представлены примеры различных программ на языке Си для микроконтроллеров Atmel AVR. Все примеры написаны под микроконтроллер ATmega16, поэтому при переносе на другие МК семейства AVR это нужно учитывать. Тактовая частота микроконтроллера во всех примерах 8 МГц (используется тактирование от внутреннего генератора). Код примеров разбит на блоки и снабжен комментариями. Проекты написаны в среде Eclipse (инструкция по установке и настройке Eclipse для AVR) и легко могут быть импортированы в Eclipse. Также можно использовать данные проекты и в среде AVR studio (изменится только структура файлов проекта). При обнаружении ошибок просьба сообщить на почту.

Blink – Самый простой пример. К порту C подключены 8 светодиодов. Светодиоды зажигаются логической единицей на линии порта. В цикле светодиоды порта включаются и выключаются. Свеобразный аналог Hello World в мире встраиваемых систем.

IO Ports – В данном примере рассматривается работа с портами ввода-вывода. К порту C подключены 8 светодиодов (линии 0-7). К линии 2 порта D подключена кнопка, с подтяжкой на землю. При нажатии кнопка выдает на линию 0 порта С уровень логической единицы. Цикл программы организован следующим образом: при запуске включается бегущий огонь, сначала загорается светодиод на линии 0 порта C, затем на линии 1 и т.д. По достижении линии 7 направление бегущего огня меняется (от 7 к 0). При нажатии на кнопку бегущий огонь останавливается и загораются одновременно все светодиоды. После повторного нажатия на кнопку бегущий огонь продолжает перемещаться с места остановки.

Dynamic Indication – В данном примере рассматривается работа с 7-сегментным индикатором. В моём случае он имеет 4 разряда (цифры). Поскольку у меня на плате установлены транзисторы для управления разрядами, то управление осуществляется выводом логической единицы и на разряды и на сегменты. Схема подключения следующая: к линиям 0-7 порта C подключены сегменты индикатора, а к линиям 0-3 порта В разряды индикатора. При запуске на индикатор выводятся цифры 1 2 3 4.

UART – В данном примере рассматривается периферийного модуля UART (универсальный асинхронный приёмопередатчик). Модуль UART можно настроить как на работу с прерываниями, так и без них (вручную, путём работы с флагами). Пример работает следующим образом: при получении байта, МК переходит в обработчик прерывания (используется только прерывание по приёму данных) и разбирает численное значение байта (0-255) на цифры, которые и выводятся на 7-сегментный индикатор. Схема подключения аналогична предыдущему примеру. Передача осуществляется по двум линиям UART (порт D линии 0-1), к которым необходимо подключить линии RX и TX преобразователя USB-UART. Для настройкки без прерываний необходимо обнулить бит RXCIE в регистре UCSRB и вручную опрашивать интерфейс в основном цикле программы.

Clock – В данном примере рассматривается реализация простых часов с 7-сегментным индикатором и парой кнопок. Только здесь уже требуется 6 разрядов, хотя секунды можно опустить. Кнопки с подтяжкой на землю. При нажатии кнопка выдает на линию высокий логический уровень. Индикатор подключается как и в предыдущих примерах (сегменты к порту C, разряды к порту B), а кнопки к линиям 2-3 порта D. Кнопка используется PD2 для установки минут, а PD3 для установки часов. По нажатию каждой из кнопок увеличивается значение соответствующего разряда (минуты или часы).

DS18B20 – В данном примере рассматривается работа с цифровым датчиком температуры DS18B20. Показания температуры выводятся на 7-сегментный индикатор. Вывод DQ датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (согласно документации). Датчик опрашивается каждые 5 секунд. Температура выводится на 4-разрядный индикатор: знак, два разряда на целуюю часть и один на вещественную. Документация к датчику здесь.

DHT11 – В данном примере рассматривается работа с датчиком температуры и влажности DHT11. Показания температуры выводятся на 7-сегментный индикатор. Вывод DATA (также SDA) датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (согласно документации). Датчик опрашивается каждые 5 секунд. Измеряются температура и влажность, но на дисплей выводится только влажность (целое двухзначное число). Документация к датчику здесь.

DHT22 – В данном примере рассматривается работа с датчиком температуры и влажности DHT22. По сравнению с DHT11 данный датчик обладает большей точностью и более широким диапазоном измерений. Показания температуры выводятся на 7-сегментный индикатор. Вывод DATA (также SDA) датчика поключен к ноге (пину) PD5. Линия должна быть подтянута к плюсу питания резистором на 4.7-10 кОм (хотя согласно документации это и необязательно). Датчик опрашивается каждые 5 секунд. Измеряются температура и влажность, но на дисплей выводится только влажность (вещественное двухзначное число с одним знаком после запятой). Документация к датчику здесь.

BMP180 – В данном примере рассматривается работа с цифровым датчиком температуры и атмосферного давления BMP180. Показания атмосферного давления выводятся на 7-сегментный индикатор. Датчик подключаетсяпо интерфейсу I2C. Линии SDA и SCL должны быть подтянуты к плюсу питания резисторами на 4.7-10 кОм. Датчик опрашивается каждые 10 секунд. Измеряются температура и давление, но на дисплей выводится только атмосферное давление в мм. ртутного столба (целое число). Документация к датчику здесь.

BH1750 – В данном примере рассматривается работа с цифровым датчиком освещенности BH1750. Показания освещенности выводятся на 7-сегментный индикатор. Датчик подключается по интерфейсу I2C. Линии SDA и SCL должны быть подтянуты к плюсу питания резисторами на 4.7-10 кОм. Датчик опрашивается каждые 5 секунд. Документация к датчику здесь.

ADC Indication – Данный пример аналогичен примеру с UART. Отличие в том, что байт берется с линии 0 порта А (линия 0 АЦП, ADC0). Микроконтроллер по таймеру производит аналого-цифровое преобразование напряжения на линии 0 порта А, (младшие 2 бита отбрасываются как шум). При измерении используется внутренняя опора 5 В. К линии PD2 порта D подключена кнопка, которая определяет режим вывода показаний. При нажатии на кнопку выводится результат измерений в виде числа от 0 до 255. Если кнопка не нажата, то результат измерений переводится в вольты и выводится на индикатор (с точностью до десятых).

Fast PWM – В данном примере показана настройка аппаратного ШИМ (широтно-импульсная модуляция, англ. PWM). К линиям 4 и 5 порта D подключены светодиоды, а к линиям 2-3 и 6-7 порта D – кнопки каналов A и B соответственно. Кнопки с подтяжкой на землю (при нажатии кнопка выдает на линию порта уровень логической единицы) Кнопки на линях 2 и 3 соответственно увеличивают и уменьшают коэффициент заполнения ШИМ (меняется яркость светодиода) канала А. Кнопки на линях 6 и 7 соответственно увеличивают и уменьшают коэффициент заполнения ШИМ канала B. Число сравнения для каждого из каналов меняется в диапазоне от 0 до 255. Для канала А шаг изменения равен 10, для канала В шаг равен 5.

HCSR04 – В данном примере рассматривается работа с ультразвуковым датчиком расстояния HCSR04. К линии PD3 подключен вывод Trigger датчика, а к линии PD2 вывод Echo. Поключение 7-сегментного индикатора аналогично предыдущим примерам. МК периодически опрашивает датчик и определяет расстояние до препятсвия в сантиметрах. После этого число разбивается на цифры и выводится на дисплей. Документация к датчику здесь.

Matrix Keyboard – В данном примере показана работа с матричной клавиатурой. Микроконтроллер динамически опрашивает клавиатуру, а затем определяет номер нажатой клавиатуры. Размер поля 3 на 3 – получаем 9 кнопок. Нажатие первых 8-ми приводит к зажиганию светодиода на соответствующей линии порта А, нажатие 9-ой кнопки зажигает все светодиоды порта А. Матричная клавиатура подключается к линиям 0-5 порта С (три столбца и три строки). В архиве схема и печатная плата матричной клавиатуры (Diptrace).

Shift Register – В данном примере рассматривается работа с модулем SPI на примере сдвигового регистра 74HC595. К регистру подключены светодиоды, в качестве линии CS используется линия 4 порта B (вывод not SS). Линия DS (14 нога) регистра идет к MOSI (PB5), линия SHCP (11 нога) к линии SCK (PB7), линия STCP (12 нога) к линии SS (PB4). Линии MR (10 нога) и OE (13 нога) должны быть подтянуты к высокому и низкому логическим уровням соответственно. По таймеру микроконтроллер меняет состояние светодиодов: поочерёдно горят то чётные светодиоды, то нечётные. Если при этом передать байт по UART’у, то он будет выведен в порт на светодиоды. Чтобы обратно переключиться в режим мигания необходимо послать по UART’у 0x00 (ноль). Документация к микросхеме 74HC595 здесь.

SG-90 Servo – В данном примере рассматривается работа с сервоприводом SG-90. Используется аппаратный ШИМ. Линия ШИМ сервпопривода подключена к каналу А аппаратного ШИМ. Кнопки поворота подключены к линиям PD2 и PD3. Кнопка на линии PD2 увеличивает длительность импульса, кнопка на линии PD3 уменьшает длительность импульса. Длительность импульса меняется от 1 до 2 мс. Описание сервомотора здесь.

RGB Lamp – В данном примере рассматривается работа с трехцветным RGB-светодиодом. Реализовано плавное переливание цветов с использованием программного ШИМ. Линии красного, зеленого и синего цветов подключаются соответственно к линиям 2, 3 и 4 порта D.

TSOP4836 NEC – В данном примере рассматривается работа с фотоприемником TSOP4836 и протоколом передачи NEC, который широко используется в инфракрасных пультах дистанционного управления. При получении команды на дисплей выводится ее код. Поключение 7-сегментного индикатора аналогично предыдущим примерам. Описание фотоприемника здесь.

WS2812 Ring – В данном примере рассматривается работа со светодиодами WS2812 с встроенным ШИМ-контроллером. К контроллеру подключено такое кольцо из 16 светодиодов (количество светодиодов в кольце можно указать в коде). Библиотека для работы с WS2812 не моя (взята на гитхабе и немного допилена, копирайт сохранён). В программе сначала задается массив цветов (красный, зеленый, синий), а затем в цикле реализуется их сдвиг и плавным изменением интенсивности. Линия IN первого светодиода подключается к линии PD2 порта D. Описание светодиодов здесь.

MFRC522 RFID – В данном примере рассматривается работа со считывателем RFID карточек MFRC522. Cчитыватель подключён к контроллеру по стандартной схеме. Библиотека для работы с MFRC522 не моя (взята на гитхабе и немного допилена, копирайт сохранён). При запуске контроллер определяет тип ридера и отправляет данные в UART. Затем идет непрерывная проверка обнаружения RFID устройств. При поднесении карточки или брелка считывается его адрес и отправляется в UART (адрес 32 бита, 4 байта). Описание считывателя здесь.

Оцените статью
Fobosworld.ru
Добавить комментарий

Adblock
detector