Уроки программирования avr на си для начинающих в atmel studio

Содержание

Atmel studio 7 руководство на русском

Программирование Arduino из Atmel Studio 7

Привет Гиктаймс. Новогодние праздники подходят к концу, все салаты съедены, шампанское выпито, и жизнь потихоньку начинает возвращаться в привычное русло. И это хорошо. Но речь совсем не об этом.
Дело, собственно, вот в чем: многие из нас, начиная свой путь программирования микроконтроллеров с платы Arduino, подходили наконец к такому моменту,
когда в родной среде Arduino IDE становилось тесновато, а крутые среды разработки типа Atmel Studio, Keil, Microsoft VS пугали обилием настроек и инструментов.
Мне, например, очень удобно работать с механизмом вкладок Arduino IDE, разрабатывая большие проекты, это чисто мое предпочтение — на самом деле очень много времени занимает перенос кода, функций и переменных в заголовочные файлы и классы. Но на самом деле, есть более весомые аргументы в пользу перехода от Arduino IDE к более серьезным инструментам разработки. Это в первую очередь, наличие отладчика. Для начинающих программистов микроконтроллеров это кажется несущественным, но когда время идет, и сложность программ увеличивается, увеличиваются и требования к работоспособности и функционалу кода МК. И тут как раз возникает необходимость понимать, и видеть, как работает твой код на микроконтроллере. Даже если ты не обзавелся каким нибудь jtag — девайсом, очень приятно наблюдать даже в симуляторе, как нужные значения падают в нужные регистры во время работы программы. Ну и конечно же, если вы всерьез решили изучить программирование микроконтроллеров и архитектуру AVR — то без дебаггера просто никак не обойтись. Я уже молчу про скрытую работу wiring — препроцессора Arduino IDE, который позволяет писать более простые программы, используя функционал библиотек Arduino, и который добавляет в программу очень много мусора, который занимает память программ контроллера, и использует вхолостую ресурсы МК. Также немаловажным фактором является скромность редактора исходного кода среды Arduino IDE. И как водиться в миру, настоящие хардкорные разработчики встраиваемых систем и автоматики пишут только на си и ассемблере, полагаясь на собственный интеллект и опыт, а не на разработки итальянских студентов (против которых ничего плохого не имею, и камней в их огород бросать не буду).
Если вы согласны с вышесказанным — значит вы уже пробовали, или только собираетесь установить и использовать Atmel Studio 7. Я сам программист начинающий, можно сказать, программирование учил очень давно в школе, это был интерпретируемый Бейсик на машинах MSX. И лишь только пару лет назад пришлось, как говорится, по долгу службы приступить к изучению и освоению си и с++. Поэтому с небольшой высоты колокольни собственного опыта, хочу порекомендовать AVR Studio, а именно Atmel Studio 7. На самом деле, эта среда доставила мне достаточно нервотрепки с ее установкой и запуском (окна я использую исключительно для работы и потехи, причем это Win 7 SP1 64), было несколько попыток установить ее с разбегу, но это заканчивалось фэйлом, пока на чистую систему я не установил обновление Windows6.1-KB3033929-x64.msu, после чего все таки мои старания были вознаграждены, и среда запустилась. После было много сказано отнюдь не литературных слов и выражений, пока среда не стала более менее адекватно работать (Atmel Studio 7 у меня жутко тормозила поначалу, на машине с хорошим Core i7 и 8 гигами шустрой ОЗУ DDR4, не пойму, что стало потом, то ли среда каким то мистическим образом прокэшировалась в системе, или же я привык, но сейчас все неплохо работает). Также я хочу подметить, что эта среда так или иначе разработана и выпущена разработчиками AVR и ARM контроллеров Atmel, и посему поддерживает все свои контроллеры, и предоставляет все необходимые для работы библиотеки на с/с++. Огромный плюсом, и как я полагаю, неотъемлемой частью является наличие ассемблера для описанных выше платформ. Также в седьмой версии программы появилась поддержка конвертации скетчей Arduino в код программы для контроллера на языке си. Опция эта работает пока что несовершенно, и неспособна преобразовывать скетчи с несколькими вкладками, из-за чего теряет пока что определенную актуальность.
Но есть у этой среды и определенный недостаток: она не поддерживает наиболее популярный, и самый дешевый программатор USBaSP, и не поддерживает из коробки возможность программирования напрямую(используя порт USB) плат Arduino. И поэтому я в этой статье хочу поделиться определенным лайфхаком, и я надеюсь, что это кому то будет действительно полезным.
Итак, приступим. Что нам необходимо иметь: ПК с установленными Atmel Studio 7, Arduino IDE желательно последней версии, и драйверами для вашей платы Arduino, ну и собственно, сам пациент. Подключаем контроллер к ПК, дальше устанавливаются драйвера, и после вы должны выполнить несколько манипуляций, но это нужно будет сделать один раз для разных плат Arduino.
Сначала открываем среду Arduino IDE, выбираем любимый наш Блинк, и включаем вывод компилятора в окно компиляции внизу редактора:

Потом компилируем скетч, не загружая его в контроллер:

После вам необходимо открыть какой нибудь текстовый редактор, и выполнить пару вещей — скопировать команды для компилятора и флаги компиляции в окно редактора, и отредактировать подобным образом:



После, открыв среду Atmel Studio 7, выбираем во вкладке Tools пункт External Tools, cоздаем новый профиль (можете сделать несколько разных профилей для каждой отдельной платы Arduino, где в соответсвующие строки вставляем наши параметры, где указаны адрес программы avrdude, и команды для компилятора:


Потом можно создать любой проект, написав, к примеру, тот же код любимой моргалки, но уже на си, и загрузить наш код в контроллер, сначала собрав ваш проект, нажав F7 (Build project), и после кликнув на пункте с именем вашего профиля программирования во вкладке Tools:

Программа ваша будет записана в память программ контроллера, загрузчик останется на своем месте, и вы всегда сможете открыть Arduino IDE и записать ваш код привычным способом. Благодарю всех за внимание, и надеюсь, что данный совет будет кому нибудь полезен.

Русификация программы Atmel Studio

После установки программы Atmel Studio весь интерфейс будет на английском языке. Кому-то, кто знаком с английским, или уже привык работать с программами с английским интерфейсом, это вполне устроит. Меня лично, такой подход создателей программы к великому и могучему не устраивает, мне более комфортно работать с русскими меню.
Оболочку для программы создавали специалисты из Микрософт, и основой ее была программа Visual Studio (они даже похожи внешне), в которой есть возможность установить национальный язык. У Atmel Studio такой возможности нет, хотя в настройках меню присутствует возможность выбрать два языка — английский или такой же, как в системе Windows (что подразумевает русский, или тот на который настроена ваша система) но меню не перестраивается, только английский. Там же есть ссылка на сайт Микрософт для загрузки файла с национальным языком, файл загружается в компьютер, но не устанавливается, требует присутствия программы Visual Studio.
Поэтому, для русификации программы, придется установить программу Visual Studio. Я надеюсь, что в дальнейшем в Atmel Studio появится возможность устанавливать национальный язык без установки дополнительных программ.
Установка Visual Studio
1. Заходим на официальный сайт Микрософт microsoft.com/ru-ru
2. В поисковом окне сайта забиваем visual studio 2015
3. В разделе Загрузки нажимаем просмотреть все и на первой же странице появляется богатый выбор из продукции Микрософта. Я для себя выбрал установку пакета Visual Studio Professional 2015 (устанавливать — так по полной, вдруг в дальнейшем пригодится, хотя все равно устанавливается только определенный базовый набор)

4. После нажатия на кнопку Скачать, появится выбор — или установить программу онлайн, или все скачать а потом установить, тут как кому нравится.

После установки Visual Studio и перезагрузки системы, в меню Atmel Studio появится возможность поменять интерфейс на русский.
Где это находится (покажу в картинках):




Нажимаем ОК, и, после перезагрузки программы, интерфейс будет на русском языке.
Сразу хочу отметить, что перевод будет не полный, кое-что останется на английском.

Итог нашей работы:

Atmel Studio и программатор USBasp

В прошлой статье я уже писал, что совместно с программой Atmel Studio мы будем использовать простой и недорогой программатор USBasp и программу для прошивки микроконтроллеров AVRDUDE_Prog. Конечно, если у вас есть программатор, совместимый с Atmel Studio, вы сможете пользоваться и им.
Эта статья для тех, кто имеет только USBasp (хотя и не только для них).
Ближайший родственник USBasp программатора, который совместим с Atmel Studio — STK500. Есть программаторы несколько сложнее USBasp — USBisp, которые можно прошить прошивкой от STK500, но у нас такой возможности нет. Мы можем только, для удобства работы с программой AVRDUDE_Prog интегрировать ее в меню Atmel Studio (вставим в меню кнопку вызова программы). Так как Atmel Studio у нас уже имеет русский интерфейс, то картинок уже не будет.

Итак, вставляем кнопку вызова программы AVRDUDE_Prog в меню:
1. Выбираем меню Сервис
2. В открывшемся окне выбираем Внешние инструменты
3. В открывшемся окне, в графе Название прописываем USBasp, а в графе Команда указываем путь до файла запуска программы AVRDUDE_Prog и нажимаем ОК. Теперь, если снова открыть меню Сервис, мы увидим перед внешними инструментами наш USBasp. Можно программу запускать и отсюда.
4. Выбираем меню Сервис а в нем настройка
5. В открывшемся окне будет два подраздела Панели инструментов и Команды. В панели инструментов нажимаем Создать. В появившемся окне прописываем имя панели инструментов — USBasp и ОК. Сразу увидите как, среди прочего, появилась новая панель USBasp.
6. Переходим в подраздел Команды и ставим галочку (точку) напротив надписи Панель инструментов. В панели инструментов (в окне) выбираем USBasp и ОК. Далее нажимаем Добавить команду. В открывшемся окне выбираем категорию Сервис. В открывшемся окне Команды выбираем Внешняя команда 1 и ОК. Закрываем окно Настроить.
После столь долгого пути и многих манипуляций, в самом конце меню (в 1 или 2 строке) вы должны увидеть кнопку USBasp. Но можете и не увидеть, все зависит от разрешения вашего экрана, она может быть спрятана внутри раскрывающегося меню

Ищем, где находится наша кнопка

И перетягиваем раскрывающееся меню на вторую строчку

Теперь мы можем запускать программу AVERDUDEProg из меню Atmel Studio.
Таким же образом можно прописать и любую другую программу

1. Основы программирования микроконтроллеров AVR

Atmel Studio для Windowsпоследняя версия: 7.0.790, обновление от 06.06.2018

  • ATMEL STUDIO
  • Тип лицензии: Крякнутая
  • Языки: Мульти
  • ОС: Windows 8, 8 64-bit, 7, 7 64-bit, Vista, Vista 64-bit, XP, XP 64-bit
  • Просмотров: 380
  • Скачано: 152

На данный момент многие люди используют разнообразный софт. Теперь с уверенностью можно сказать о том, что практически каждый человек использовал Atmel Studio. Эта программа в своей сфере считается достаточно уникальной. Она позволяет выполнять разнообразные прошивки. Если вам интересно, что представляет собою программа, тогда необходимо изучить эту статью.

Первым, что вы сможете увидеть после перехода в систему это дизайн программы. Он считается достаточно интересным и не вызывает дискомфорта. Теперь для создания новый прошивки вам необходимо пройти уже привычную процедуру File-New project. После выполнения этого процесса вы сможете выбрать необходимый тип файла.

Теперь благодаря определенным дополнениям достаточно легко можно понять, сколько оперативной памяти имеет определенный микроконтроллер.

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

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

Начало работы с AVR Studio 4 (урок 1)

Для работы с AVR Studio 4 необходимо само собой её установить. Если она уже установлена, то можете пропустить этот шаг.

Установка:
создаешь каталог c:/avr/ – тут будут лежать рабочие программы.
создаешь каталог например c:/works/ – тут будут лежать твои работы.
надо что бы были короткие пути, что бы не было проблем с ними.

Дальше, качаешь и устанавливаешь в каталог c:/avr/
WinVR
AVRStudio4_SP3

Есть вообще AVRStudio5 но и AVRStudio4 пока вполне хватает.

Вся работа будет проходить в AVRStudio4, WinAVR нужна только из-за библиотеки AVR-GCC (Для того, что бы можно было писать на Си)
НО! первым надо установить именно WinAVR , иначе библиотека AVR-GCC не подцепится.

Дальше запускаешь AVRStudio4 и создаешь проект.

Тут думаю разберешься.
AVR-GCC для того, что бы писать на Си
Atmel Avr Assembler соответственно для ассемблера.

Начинать разбираться с МК лучше с нуля. А это значит с Ассемблера, значит создаешь тот, который Atmel AVR Assembler.

Потом выбирай микроконтроллер Atmega8.

дальше нужно выбрать симулятор. выбирай: AVR Simulator — Amega8

ну теперь нажимай финишь.

когда создастся проект, будет большой, белый, чистый лист. тут будет код.

немного про содержимое этого листа

“комментарии” – это текст, пропускаемый компилятором, при компиляции.
перед началом комментария должен стоять спец символ, пользуюсь символом ; “точка с запятой”, есть еще “дабл сшеш” (//),
вот примеры комментариев

/* * Комментарий такого види(многострочный), * обычно используется для * сопроводительной информции * об исходном коде, т.е. * название, разработчик и т.д. */ NOP // Такой комментарий в основном используется для пояснения назначения команды, или куска кода SLEEP ; такой комментарий тоже как и предыдущий, можно использовать для пояснения (для заметок) в коде

команды записываются в каждой строчке. т.е. одна команда – одна строчка.
допустим есть команды с двумя “параметрами”, с одним, или без ничего

MOV R16, R17 ; два параметра INC R16 ; один параметр SEI ; без параметров

С этим все ясно. дальше сложнее. Каждая команда, имеет размер 1, 2 или 3 байта.

MOV R16, R17 ; три байта INC R16 ; два байта SEI ; один байт

Видите связь размера команды с параметрами?

У каждого микроконтроллера свой ассемблер, хотя мнимоника у них похожа, т.е. команда MOV у мк одной серии будет выглядеть в машинном коде допустим 0x12 а у другого 0x55.
что бы при компиляции, скомпилировалось в нужном нам коде мы должны сказать компилятору, для какого мк у нас пишется программа.
это вообще выбирается при создании проекта.
По этому мы выбрали микроконтроллер Atmega8.

Но и тут не все. для облегчения нашей жизни, в AVRStudio4 есть набор констант, которые именуются вроде как “Макроассемблер”.

Для тог, что бы их подгрузить нужно в начале кода вставить строчку

.include m8def.inc // командой .include, мы подгрузили файл m8def.inc ;и теперь нам станет легче 😉

в самом начале кода, ставится таблица прерываний. Что это такое и как это работает, объясню в другой заметке. Но а пока, будем писать её так:

RJMP RESET ; Reset Handler RETI; RJMP EXT_INT0 ; IRQ0 Handler RETI; RJMP EXT_INT1 ; IRQ1 Handler RETI; RJMP TIM2_COMP ; Timer2 Compare Handler RETI; RJMP TIM2_OVF ; Timer2 Overflow Handler RETI; RJMP TIM1_CAPT ; Timer1 Capture Handler RETI; RJMP TIM1_COMPA ; Timer1 CompareA Handler RETI; RJMP TIM1_COMPB ; Timer1 CompareB Handler RETI; RJMP TIM1_OVF ; Timer1 Overflow Handler RETI; RJMP TIM0_OVF ; Timer0 Overflow Handler RETI; RJMP SPI_STC ; SPI Transfer Complete Handler RETI; RJMP USART_RXC ; USART RX Complete Handler RETI; RJMP USART_UDRE ; UDR Empty Handler RETI; RJMP USART_TXC ; USART TX Complete Handler RETI; RJMP ADC ; ADC Conversion Complete Handler RETI; RJMP EE_RDY ; EEPROM Ready Handler RETI; RJMP ANA_COMP ; Analog Comparator Handler RETI; RJMP TWSI ; Two-wire Serial Interface Handler RETI; RJMP SPM_RDY ; Store Program Memory Ready Handler

После этого идет уже сам код

RESTART: ; маркер инициализации MAIN: NOP ; маркер главного цикла RJMP MAIN

Но тут есть одна (точнее не одна, а много) особенностей.

Для удобства написания кода, для его понятности и для облегчения относительных переходов, нам подарили маркеры, как они выглядят? “RESET:” и “MAIN:” это маркеры, в их именах могут содержаться почти любые символы латинского алфавита и цифры. Маркеры не могут иметь имена функций и команд, допустим “NOP”.
Как к ним переходит? Допустим командой RJMP.

Так же, из Маркеров, можно сделать подпрограмму(процедуру), по завершению которой, мы вернемся туда, от куда её вызывали. Для вызова её, используем команду “RCALL (подпрограмма)”, а что бы вернуться из Подпрограммы(процедуры), нужно закончить её командой “RET”. У нас должен получиться такой код:

RESTART: MAIN: NOP RCALL PPP1 ; вызываем подпрограмму RJMP MAIN PPP1: NOP RET ; выходим из подпрограммы

Как работает команда “RCALL”, при её вызове, адрес из какого места её вызвали, помещается в СТЕК, а по вызове команды “RET”, извлекается из регистра “стек”. СТЕК нужно инициализировать.

Что бы нам работать с нашим мк, нужно его инициализировать. т.к. мк, это устройство универсальное, в нем есть много портов ввода/вывода, и периферийных устройств. таких как УСАПП, ШИМ, ЦАП, АЦП и т.д. Первым делом в инициализации мк нужно указать начало “стека”. Инициализацию мы проводим после маркера “RESET:”.

LDI R16,HIGH(RAMEND) OUT SPH,R16 LDI R16,LOW(RAMEND) OUT SPL,R16

Если бы мы не вводили команду .include “m8def.inc” в начале кода, то нам пришлось бы писать так:

LDI R16,0x04 OUT SPH,R16 LDI R16,0x5f OUT SPL,R16

Разница существенная, на мой взгляд.

СТЕК, это память магазинного типа: (последний вошедший, выходит первым).
Магазинного типа – это не супермаркет, а рожок от автомата. надеюсь все представили как в него заряжаются патроны и как они потом от туда извлекаются.
Нужно уделять очень большое внимание памяти СТЕК, т.к. любая незначительная ошибка в работе с ним, может привести к срыву стека. Это на столько важная тема, что я решил посветить ей целую тему и напишу её в отдельной заметке.

Таким образом у нас получился такой код:

.include m8def.inc RJMP RESET ; Reset Handler RETI; RJMP EXT_INT0 ; IRQ0 Handler RETI; RJMP EXT_INT1 ; IRQ1 Handler RETI; RJMP TIM2_COMP ; Timer2 Compare Handler RETI; RJMP TIM2_OVF ; Timer2 Overflow Handler RETI; RJMP TIM1_CAPT ; Timer1 Capture Handler RETI; RJMP TIM1_COMPA ; Timer1 CompareA Handler RETI; RJMP TIM1_COMPB ; Timer1 CompareB Handler RETI; RJMP TIM1_OVF ; Timer1 Overflow Handler RETI; RJMP TIM0_OVF ; Timer0 Overflow Handler RETI; RJMP SPI_STC ; SPI Transfer Complete Handler RETI; RJMP USART_RXC ; USART RX Complete Handler RETI; RJMP USART_UDRE ; UDR Empty Handler RETI; RJMP USART_TXC ; USART TX Complete Handler RETI; RJMP ADC ; ADC Conversion Complete Handler RETI; RJMP EE_RDY ; EEPROM Ready Handler RETI; RJMP ANA_COMP ; Analog Comparator Handler RETI; RJMP TWSI ; Two-wire Serial Interface Handler RETI; RJMP SPM_RDY ; Store Program Memory Ready Handler RESET: LDI R16,HIGH(RAMEND) OUT SPH,R16 LDI R16,LOW(RAMEND) OUT SPL,R16 RGMP RESET MAIN: NOP ; маркер главного цикла RJMP MAIN

На данном этапе, можно скомпилировать проект и запустить его для отладки, но по скольку код у нас ничего не делает, можно будет выявить только синтаксические ошибки в коде.

Для правильного процесса отладки, необходимо задать эмулятору частоту, с которой будет работать МК, это делается только после компиляции и запуска отладки,
значит находим в панели меню “Build”, раскрываем её и видим “Build and Run”, после чего, мы увидим желтую стрелочку на против первой команды в нашем листинге кода. Теперь мы ищем в панели меню “Debug” и нажимаем “AVR Simulator Options”, открывается такое окно:

В котором мы можем поменять МК и его частоту, так же, на панели с права, мы видим некоторую информацию о нашем МК: его максимальную частоту, объемы памяти(EEPROM, RAM, FLASH). Теперь открываем даташит на Atmega8, на странице 203 (общий список регистров) и 205 (общий список команд) и приступай к написанию своей программы.
И запомни, не бойся экспериментировать с симулятором, он от этого не сломается!

Настало время написать первую программу для нашего микроконтроллера!

Для выполнения данного урока, Вам пригодится:

  1. Микроконтроллер (Подойдет почти любой микроконтроллер семейства AVR, однако , лучшим выбором по соотношению цена/функционал станет AtMega8).
  2. Светодиод (Так же любой, однако при покупке уточните его номинальный ток, и падение напряжения).
  3. Резистор (Какой именно, рассчитаем далее).
  4. Программатор.
  5. Провода соединительные.
  6. Источник питания 5v.
  7. Плата макетная (Для Вашего удобства).

Начнем с написания прошивки.

Прошивка(Программа) — Набор инструкций(команд) микроконтроллера, представленный в виде конечного файла(специального формата), используемого в дальнейшем при работе контроллера.

1.Открываем Atmel Studio, создаем проект на языке AVR C или AVR ASSEMBLER и выбираем модель Вашего микроконтроллера.

В окне редактора исходного кода пишем:

Урок 2,AVR C HELLO WORLD C

Урок 2.AVR Assembler hello world

Нажимаем Build-Build Solution. После выполнения данных операций, в папке проекта появится файл формата .hex. Это и есть наша прошивка!

2.Далее, собираем следующую схему:

Резистор R1 необходим для ограничения тока протекающего через светодиод LED1.

Например, возьмем светодиод с напряжением питания 2.2В и током питания 10 мА(0.01А). Напряжение питания соответственно равно 5В.

Согласно приведенной выше формуле, получим:

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

В данном случае берем резистор стандартного значения 330 Ом.

А теперь настало время вдохнуть жизнь в нашу схему!

3.Подключаем программатор к контроллеру, и записываем в его память прошивку полученную выше.

Возможно, для подключения программатора придется временно отсоединить микроконтроллер от схемы. Ничего страшного в этом нет, однако, следует быть предельно внимательным и не забыть отключить 5v подаваемые на схему.

Вернув контроллер на его место в схеме(Разумеется, если Вам пришлось его отсоединить), подаем 5v питания на контроллер.

Если все сделано верно, вы увидите что светодиод зажигается и гаснет с постоянной частотой.

Поздравляем, Вы только что собрали Ваше первое устройство с использованием микроконтроллера!

Если что то не получилось, то Вы всегда можете написать об этом в комментариях к данной статье!Наша команда всегда готова ответить на все Ваши вопросы!

Спасибо за внимание!

Администрация сайта MKPROG.RU.

Другие уроки цикла.

Копирование, воспроизведение, цитирование данного материала или его частей разрешено только с письменного разрешения администрации сайта MKPROG.RU.

Программирование Arduino на C. Часть 1

Поднимем вопрос программирования Arduino на языке Си. Зачем это может понадобиться, ведь на языке Arduino писать значительно проще? Во-первых, код на Си весит намного меньше, чем на Arduino (насколько меньше увидите дальше). Во-вторых, он может выполняться быстрее (для задач, где критична высокая скорость). Кроме того, это может стать первым шагом при освоении собственно микроконтроллеров. Как всегда здесь не будет теории, только практика.

Для начала необходимо подключить библиотеку, позволяющую отправлять-принимать сигналы. Делается это командой

1 #include avr/io.h

Если на Arduino было необходимо наличие функций loop и setup, то на Си должна быть функция main, возвращающая тип int. Внутри этой функции и будет находится наш код.

1 2 3 int main (void)

Поставим себе простейшую задачу — зажечь светодиод на порту №13. И тут мы столкнемся с тем, что собственно на микроконтроллере нет 13 порта. Посмотрим распиновку (pinout) микроконтроллера, установленного в Ардуино (atmega328p).

Тут обращаем внимание на PB0 — PB7, PC0 — PC6, PD0 — PD7. Это и есть порты для подключения устройств, с ними и предстоит работать. Посмотрим, как эти порты соотносятся с портами Arduino.

Мы задались целью зажечь светодиод на 13 порту. По распиновке Arduino мы видим, что там находится порт PB5. Собственно, правильнее сказать, что порт B, 5 бит. В программе будем работать сразу со битами порта B (0-7), но постараемся не затрагивать биты кроме 5.

Сначала нужно обозначить B5 как выход, то, что на Ардуино делалось командой pinMode (13, OUTPUT).

На Си для этого существует команда DDRB, где B — порт (соответственно, могло быть DDRC и DDRD).

У порта B 8 битов, каждый из которых может быть настроен на выход (1) и вход (0). Поэтому, мы можем задать двоичное число, где каждому биту соответствует 0 или 1.

1 DDRB = 0b00000001

говорит о том, что 0 бит порта B, т.е. PB0 (8 порт Ардуино) будет выходом (OUTPUT), остальные — входом (INPUT). 0b перед числом позволяет указывать двоичную запись числа.

Так как мы работает с PB5, то 1 мы должны поставить в 5 бит

1 DDRB = 0b00100000

Теперь нужно подать напряжение на данный порт. Делается это командой PORTB, где B — снова порт. Напряжение подается единицей, отсутствие напряжения — 0. По аналогии запишем команду

1 PORTB = 0b00100000

чтобы подать напряжение на 5 бит.

1 2 3 4 5 6 #include avr/io.h int main (void)

Что в этом коде нехорошо, так это то, что мы указывали сразу все биты одного порта. Иногда мы не знаем заранее, подается питание на тот или иной бит и изменять мы его не должны, а значит, мы не можем сами подавать туда 0 или 1. Поэтому важно уметь настраивать нужный бит, без изменения остальных.

Для этого потребуется знание логических операций и операций над битами.

Результат ИЛИ равен 1 если хотя бы один из операндов равен 1.

a b ИЛИ
0 0 0
0 1 1
1 0 1
1 1 1

Результат И равен 1 если оба операнда равны 1.

a b И
0 0 0
0 1 0
1 0 0
1 1 1

Побитовые сдвиги влево и вправо ( и )

Данные операции сдвигают все биты числа вправо или влево на заданное количество позиций.

Например, запись 12 означает, что биты изначального числа 00000001 сдвинутся влево на 2 позиции и получится 00000100.

Воспользуемся данными операциями, чтобы работать только с необходимыми битами портов.

Мы должны PB5 настроить на выход. Сделаем это так:

15 это 1 в 5 бите, т.е. 0b00100000. Применяем логическое ИЛИ для текущего состояния порта B и данного числа. Так как 1 находится только в 5 бите, то и в результате изменится лишь 5 бит порта B (станет 1), остальные биты останутся без изменений. Результат операций перезаписывается в DDRB.

Тоже самое проделаем и для отправки сигнала:

Отладка В AVR STUDIO

1. Запускаем АVR Studio 4, проект создавать не нужно.

3. Выбираем файл для загрузки в AVR Studio 4.

Выбрав файл с расширением .obj, отладку можно осуществлять в кодах Ассемблера. Следует обратить внимание на то, что проект содержит три файла (.asm, .inc и .vec) и отладка начинается с файла .vec, содержащего векторы прерываний. Курсор отладки (желтая стрелка) установлен на команде rjmp reset. После нажатия кнопки Step Into (Fll) курсор переходит на обработчик сброса, расположенный в файле .asm, и дальнейшая отладка продолжается в обычном режиме. Чтобы пропустить команды, добавленные компилятором, и перейти к отладке кода, написанного программистом, нужно установить курсор на первую команду процедуры main О и нажать кнопку Run to cursor. Все команды до курсора будут выполнены. Проект можно просмотреть в окне Disassembler, которое открывают, выбрав в меню View;Disassembler, Отладку можно продолжить в этом окне.

Для отладки программы на языке Си выбираем файл с расширением .cof.

4. Устанавливаем параметры отладки в меню Debug; AVRSimulator Options: АТх8515, частота 1 МГц, протоколирование порта РВ с выводом на экран.

5. Содержимое используемых регистров ввода;вывода МК можно проконтролировать несколькими способами:

а) непосредственно просматривая их содержимое на вкладке НО панели Workspace;

б) анализируя область памяти регистров ввода;вывода

в) присвоив их значения переменным, которые в дальнейшем просматривают в окне Watch.

В нашем случае имеем одну переменную timer, которая принимает значение таймера;счетчика TCNTO. Открываем окно Watch, выбрав команду меню View;Watch, и перетаскиваем мышью эту переменную в столбец Name. Пока переменная находится вне зоны видимости отладчика, в столбце Value будет записано Not in Scope. Подготовка к отладке завершена.

6. В начале процесса отладки и при нажатии кнопки сброса Reset курсор отладки устанавливается на первой строке процедуры main (). Выполнение программы можно контролировать, открыв окно Disassembler, однако имея программу на языке Си, значительно удобнее отлаживать программу в окне Си-программы.

7. Нажимая кнопку Step Into (Fll), наблюдаем за изменением содержимого регистров ввода;вывода микроконтроллера. Одно из преимуществ отладки на Си – использование только программных инструкций, способствующее ускорению процесса отладки. В цикле for (;;) командой Ассемблера sleep микроконтроллер переводится в режим пониженного энергопотребления.

8. Занесем в счетчик TCNTO значение 2. При разомкнутой кнопке SWO (состояние 1) эмулируем замыкание кнопки SW2 (состояние 0), что приведет к вызову обработчика прерывания. При вызове процедуры delay_ms<) отладчик не входит в нее, но вызов задерживает его работу и изменяет значение счетчика циклов.

9. Установив курсор на команде sleep, выполним команду Run to Cursor (выполнить до курсора). После останова симуляции, что обнаруживается по желтому индикатору в строке состояния, в окне Output получим список сообщений (отчет), в котором значение 0x81(10000001) соответствует готовности схемы (светодиод LED7 выключен, LED6 включен), значение OxCl(11000001) – погашены оба светодиода, 0x41(01000001) – LED6 погашен, LED7 включен. Список сообщений:

Длительность включения светодиода LED7 составляет 0,503 с.

11. Компилируем в CodeVision AVR, установив в окне Configure тип выходного файла Intel HEX. Загрузив полученный файл с расширением .hex в микроконтроллер STK500 и изменив на вкладке Board окна STK500 частоту, проверяем работу программы. Соединяем РВ6: РВ7 – LED6:LED7, SWO – РВО, SW2 – PD2. В исходном состоянии светодиод LED6 включен, LED7 выключен. Нажав несколько раз на кнопку SWO, затем на кнопку SW2, наблюдаем мигание светодиода LED7 с частотой 1 Гц. В это время светодиод LED6 выключен. После завершения мигания LED6 вновь включается, а устройство переходит в режим ожидания.

Работа над проектом с использованием языка Си позволяет сделать ряд наблюдений, касающихся наглядности программ, размеров кода, отладки и их переносимости.

Наглядность программы. Язык высокого уровня позволяет использовать сложные структуры данных, такие, как массивы, строки, списки, записи, обеспечивает максимальное удобство при написании циклов и ветвлений, избавляет программиста от написания рутинных фрагментов программ.

Программирование на Ассемблере требует знаний всех ресурсов микроконтроллера. Программа, написанная на Ассемблере, не всегда наглядна, разобраться в коде достаточно сложно, при использовании микроконтроллеров с RISC-архитектурой возникают проблемы с программированием сложных операций, таких, как умножение и деление, с обработкой структур данных.

Размер кода. При использовании всех возможностей языка Си программа может быть очень компактной, однако, если сравнивать откомпилированные коды, оценки могут измениться. Код, написанный на Ассемблере, минимален по размеру и оптимизирован под конкретную задачу, что позволяет получить высокую скорость работы программы. Компилятор же оперирует фрагментами кода по общим правилам. Так, в примере со светодиодами в начале работы программы 8.1 обнуляются все регистры микроконтроллера и оперативная память SRAM, при входе в процедуру прерывания регистры сохраняются в стеке, а затем восстанавливаются при выходе. Однако в приложении работа с памятью не предусмотрена – используется всего лишь несколько регистров.

Отладка. Если программа пишется на языке высокого уровня, а отлаживать предполагается откомпилированный код, то весь процесс может занять больше времени, чем написание и отладка программы на Ассемблере. Вместе с тем написание и отладка на языке Си программ, ориентированных в большей степени на обработку данных, проще, чем при использовании Ассемблера.

Переносимость. Изменение частоты синхронизации микроконтроллеров, очевидно, влияет на длительность выполнения процедур. Если время выполнения должно остаться неизменным (в нашем случае это время включения светодиода), потребуется вносить изменения в программу на Ассемблере, заново пересчитывая коэффициенты в циклах задержки. В программе на Си необходимо только заменить частоту в конфигурации проекта и компилятор пересчитает все автоматически, что, безусловно, проще.

Учитывая, что откомпилированный код всегда больше исходного, написанного на Ассемблере, и принимая невозможность простой его оптимизации, можно сделать выводы о предпочтении того или иного языка программирования в зависимости от сложности и направленности задачи, наличия средств отладки, доступного размера памяти микроконтроллера, требуемого быстродействия процедур, сроков проектирования и т. д.

В заключение приведем ряд рекомендаций по написанию программ на языке Си для микроконтроллеров. Для уменьшения размера программного кода рекомендуется:

– компилировать с оптимизацией по размеру;

– использовать локальные переменные, а не глобальные, так как первые хранятся в регистрах, а вторые – в ОЗУ;

– использовать по возможности беззнаковые типы данных меньшего размера;

– если глобальная переменная используется только в одной функции, она должна быть объявлена как Static,

– использовать конструкцию for (;;) для бесконечных циклов;

– использовать циклы с декрементом и конструкцию <> while <выражение)’,

– выполнять доступ в память непосредственно, не используя указатели;

– использовать макросы вместо функций для подзадач, компилируемых в две-три команды Ассемблера.

Для уменьшения требований к памяти SRAM следует:

– константы и литералы располагать в памяти программ, объявляя их с помощью директивы Flash\

– избегать объявления глобальных переменных, если они на самом деле локальные, так как последние размещаются динамически и убираются из памяти, когда выходят из зоны видимости;

– правильно оценивать размер программного стека (Data Stack Size), который необходимо указывать в настройках проекта


Источник: t-31.ru