Порядок програмування мікроконтролерів avr. Самопрограмування мікроконтролерів AVR. Як прошивати контролер, і які додаткові прилади та аксесуари потрібні для зручної роботи з ними

Головна / Контакти


Що таке програма
Що таке алгоритм

Я, мабуть, трохи поспішив, назвавши статтю «Програмування мікроконтролерів AVR – перший крок». Швидше, ця стаття, як і всі наступні, — маленький крок у світ мікроконтролерів. І таких "кроків" у нас буде багато, поки не дійдемо до того моменту, коли зможемо сказати: "Мікроконтролер - останній крок". Але й це, швидше за все, в галузі фантастики — не можна осягнути неосяжне, — світ мікроконтролерів постійно розвивається і вдосконалюється. Наше завдання — зробити перший крок, логічним результатом якого має стати перша, самостійно розроблена та зібрана конструкція на мікроконтролері. А далі - далі кожен попливе своєю дорогою у вдосконаленні отриманих на сайті знань. І тоді завершальну статтю можна буде назвати так: "Програмування мікроконтролерів - останній крок першого кроку"(треба ж, як загнув!).
І так приступаємо.

Три умови для охочих освоїти мікроконтролер

1. Бажання та наполегливість у досягненні поставленої мети
Цей пункт, як на мене, — найголовніший. Не буде бажання, а ще гірше – наполегливого бажання, то й не буде результату. Головне не пасувати і не зупинятися, виявіть наполегливість - і все вийде (і не тільки у справі освоєння мікроконтролерів).
2. Знання пристрою мікроконтролера.
Важливий фактор. Адже, погодьтеся, не знаючи як влаштований мікроконтролер, що він має у своєму розпорядженні, як це все працює, ми не зможемо використовувати всі можливості мікроконтролера, вичавити з нього все, на що він здатний.
Можливо і не варто дуже глибоко копатися у «нутрощі» мікроконтролера, але основне, так би мовити - ази, ми знати повинні (цим ми і займатимемося на сторінках сайту - вивчати ази роботи з мікроконтролером).
3. Знання команд управління мікроконтролерів.
Мікроконтролер, як собака (таке цікаве порівняння), буде дивитися на нас розумними очима і виляти своїм хвостом, поки не подамо йому команду на виконання якихось дій.
На відміну від розумного собаки, мікроконтролер розуміє набагато більше команд – понад 130 штук.
Так ось, щоб мікроконтролер не тільки виляв хвостом, а й виконував потрібну нам роботу, необхідно знати команди управління ним.
Відразу хочу сказати, для початку не треба зубрити всі 130 команд, достатньо знання і половини (і навіть менше). До того ж, багато команд дублюють один одного. Але чим більше команд ми знатимемо, тим ефективніше ми зможемо керувати мікроконтролером і тим красивіше та елегантніше виходитимуть з-під нашого пера програми.

Отже, якщо у вас є наполегливе бажання освоїти мікроконтролер, тоді продовжуємо.

Що таке програма

Які завдання ви покладаєте на мікроконтролер, і як він їх виконуватиме, визначається закладеною в нього програмою– програмою яку для мікроконтролера складаєте ви самі.

Програма(у перекладі це слово означає – “припис”) – попередній опис майбутніх подій чи дій.

Наприклад, ми хочемо, щоб мікроконтролер блимав світлодіодом. Досить просте завдання, але для того, щоб мікроконтролер виконав її, ми, попередньо, повинні крок за кроком описати всі дії мікроконтролера. написати програму, яку він повинен виконати для отримання потрібного нам результату - світлодіод, що миготить.
Щось на кшталт такого:
♦ Запалити світлодіод:
- Налаштувати виведення мікроконтролера, до якого підключений світлодіод, для роботи на виведення інформації
- подати на цей висновок логічний рівень, який дозволить запалити світлодіод
♦ Зачекати деякий час:
- перейти до підпрограми, що формує паузу (яку теж потрібно "прописати")
- По виконанню підпрограми паузи повернутися в основну програму
♦ Погасити світлодіод:
- подати на виведення мікроконтролера логічний рівень, що гасить світлодіод
і так далі.

З терміном Програманерозривно пов'язаний інший термін – Алгоритм.

Що таке алгоритм

Алгоритм- Набір інструкцій, що описують порядок дії для досягнення потрібного результату.

Якщо у програмі ми докладніше прописуємо всі діїмікроконтролера, то в алгоритмі, - ми визначаємо порядок діймікроконтролера, на основі яких ми потім створимо програму. За аналогією з вищенаведеним прикладом:
♦ Запалити світлодіод
♦ Зачекати деякий час
♦ Погасити світлодіод
і так далі.
Таким чином, алгоритм – це попередник програми. І чим ретельно і продумано буде створено алгоритм, тим простіше створюватиме програму.

Мова програмування

На жаль, якщо улюбленому собачці ми можемо подавати команди людською мовою, то спілкування з мікроконтролером має відбуватися мовою, яка зрозуміла йому — мовою мікроконтролерних команд.

Команди для мікроконтролера мають вигляд набору одиниць та нулів, типу:
00110101 011000100
так звані - коди команд, А коди команд - це мова, яка розуміє мікроконтролер. А для того, щоб перекласти нашу мову спілкування на мову мікроконтролера – у ці набори нулів і одиниць, існують спеціальні програми.
Ці програми дозволяють описати порядок роботи для мікроконтролера більш-менш зрозумілою для нас мовою, а потім перекласти цей порядок мовою зрозумілою мікроконтролеру, в результаті чого виходить так званий машинний код- Послідовність команд та інструкцій (ті самі нулі та одиниці) які тільки і розуміє мікроконтролер. Текст програми, написаний програмістом, називається вихідним кодом. Переклад програми з мови програмування (вихідного коду) мовою мікроконтролера (машинний код) проводиться трансляторами. Транслятор перетворює текст програми на машинні коди, які потім записуються на згадку про мікроконтролера.
У цих програмах порядок роботи мікроконтролера описується спеціальною мовою – мовою програмування.

Мова програмування– це спосіб передачі команд, інструкцій, чіткого керівництва до дії мікроконтролера.

З багатьох мов програмування можна назвати два типу:
мови програмування низького рівня
мови програмування високого рівня
Чим вони відрізняються. А відрізняються вони своєю близькістю до мікроконтролера.

На зорі зародження мікропроцесорної техніки програми писали в машинних кодах, тобто весь алгоритм роботи послідовно прописували у вигляді нулів і одиниць. Ось так, наприклад, могла виглядати програма:
01010010
01000110
10010011
Важко, навіть професіоналу, розібратися у такій комбінації із двох цифр. Для полегшення свого життя програмісти стали створювати перші мови програмування. Так ось, чим ближче мова програмування до такого набору нулів і одиниць тим більше він "низького рівня", а чим далі від них - тим більше "високого рівня".

Найпоширеніші мови програмування для мікроконтролерів:
- мова низького рівня - Асемблер
- мова високого рівня - С (Сі)
Давайте подивимося на прикладі їхньої відмінності (ці приклади абстрактні).
Допустимо нам треба скласти два числа: 25 та 35.
У машинних кодах ця команда може мати такий вигляд:
00000101 1101001
Мовою низького рівня:
ADD Rd, Rr
Мовою високого рівня:
25+35
Відмінність мов низького та високого рівня видно неозброєним оком.
Але давайте копнемося в цих прикладах глибше. Приклад машинного коду не будемо розбирати, оскільки він ідентичний прикладу на Асемблері. За своєю суттю, асемблерні команди це ті ж машинні коди (команди) яким просто, щоб не заблукати в нулях і одиницях, присвоєні буквені абревіатури. Асемблерною командою ADD Rd, Rr ми ставимо мікроконтролеру завдання скласти два числа, які знаходяться (а для цього ми повинні їх туди попередньо записати) – перше Rd, друге Rr, а результат додавання помістити в Rd. Як бачите, ми ставимо дуже конкретне завдання мікроконтролеру: де взяти, що з цим зробити і куди помістити результат. І тут ми працюємо безпосередньо з микроконтроллером.
Команда мовою високого рівня: 25+35, звичний для нас математичний запис, що тішить наше око. Але в цьому випадку ми не працюємо безпосередньо з мікроконтролером, ми просто ставимо йому завдання скласти два числа. Результат і послідовність дій у цьому випадку буде той же, що і при виконанні асемблерної команди: спочатку ці два числа будуть кудись записані, потім складені а результат кудись поміщений.
І ось тут криється головна відмінність мов високого та низького рівня. Якщо в Асемблері ми контролюємо весь процес (хочемо ми того, чи ні): ми знаємо де записані ці два числа, і ми знаємо де буде результат, то в мові високого рівня ми процес не контролюємо. Програма сама вирішує куди записати цифри і куди помістити результат. Найчастіше нам це і не треба знати, адже для нас головне підсумок – число 60 на виході. Як результат, програми на мовах високого рівня більш читані (спірне питання), приємні для ока (спірне питання) і менше за розміром - адже нам не доводиться "лізти у всі дірки" і розписувати кожен крок мікроконтролера, програма це робить потім за нас, коли компілює її – перекладає машинні коди. Але тут є мінус. Два однакові алгоритми написані на Ассемблері і на Сі, після перетворення їх у машинні коди матимуть різний розмір: програма написана на Ассемблері буде на 20-40% коротше програми написаної на Сі – чорт його знає, яким шляхом йде Сі для досягнення потрібного нам результату . І трапляються випадки, коли немає довіри до мови високого рівня і в програмі на Сі роблять вставки коду, написані на Асемблері.

Просунуті програмісти, як правило, знають кілька мов програмування, творчо поєднуючи їхні можливості та переваги в одній програмі. Ну а нам, любителям, треба знати хоча б одну мову (для початку), і починати треба (а я в цьому твердо впевнений) із мови низького рівня – Асемблера.

програм та даних розділені (на відміну від класичної архітектури
фон Неймана у звичайних комп'ютерах, де загальна пам'ять). Роздільні шини для
цих областей пам'яті значно прискорюють виконання програми: дані та
команди можуть обиратися одночасно.

32 регістру загального призначення (РВН). Atmel була першою компанією, далеко
відійшла від класичної моделі обчислювального ядра, в якій викона-
ня команд передбачає обмін даними між АЛУ та запам'ятовуючими
осередками у спільній пам'яті. Введення РОН у такій кількості (нагадаємо, що в
архітектурі х 86 всього чотири такі регістри, а в x 51 поняття РОН, як таке,
відсутня) у ряді випадків дозволяє взагалі відмовитися від розташування гло-
бальних і локальних змінних в ОЗУ та від використання стека, операції з
яким ускладнюють та захаращують програму. В результаті структура ас-
семблерна програма наближається до програм мовами високого рівня.
Щоправда, це призвело до деякого ускладнення системи команд.
яких для AVR більше, ніж в інших RISC-родинах (хоча значна
частина інструкцій – псевдоніми).

Flash-пам'ять програм(10 000 циклів стирання/запис) з можливістю
внутрішньосистемного перепрограмування та завантаження через послідовний
канал прямо у готовій схемі. Про переваги такого підходу, який нині став
загальноприйнятим, докладно розказано в у веденні.

Окрема область енергонезалежної пам'яті(EEPROM, 100 000 циклів
стирання/запис) для зберігання даних, з можливістю запису програмним
шляхом або зовнішнього завантаження через SPI-інтерфейс.

Вбудовані пристрої для обробки аналогових сигналів: аналоговий
компаратор та багатоканальний 10-розрядний АЦП.

Сторожовий таймер, що дозволяє здійснювати автоматичне перезавантаження
контролера через певні проміжки часу (наприклад, для виходу з
"сплячого" режиму).

Послідовні інтерфейси SPI, TWI (I

C) та UART (USART), дозволяю-

щі здійснювати обмін даними з більшістю стандартних датчиків та
інших зовнішніх пристроїв (у тому числі таких, як персональні комп'ютери)
апаратні засоби.

Таймери-лічильникиз передустановкою та можливістю вибору джерела рахунок-
них імпульсів: як правило, один-два 8-розрядних і як мінімум один
16-розрядний, у тому числі можуть працювати в режимі багатоканальної 8-, 9-,
10-, 16-бітової широтно-імпульсної модуляції (PWM).

Можливість роботи при тактовій частотівід 0 Гц до 16-20 МГц.

Діапазон напруги живлення від 2,7 до 5,5 В(у деяких випадках від 1,8 або
до 6,0 В).

Численні режими енергозбереження, що відрізняються кількістю вузлів,
що залишаються підключеними. Вихід із "сплячих" режимів по сторожовому
таймера або за зовнішніми перериваннями.

Вбудований монітор живлення- детектор падіння напруги (Brown-out
Detection).

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

Сімейства AVR

У 2002 р. фірма Atmel розпочала випуск нових підродин 8-розрядних МК на базі
AVR-ядра. З того часу всі МК цього сімейства діляться на три групи (підсімейст-
ва): Classic, Tiny та Mega. МК сімейства Classic (AT90S) xxxx) вже не випускаються;
найдовше у виробництві "затрималася" дуже вдала (проста, компактна та
швидкодіюча модель) AT90S2313, але і вона була в 2005 р. замінена на
ATtiny2313. Всі "класичні" AVR з першими цифрами 2 та 8 у найменуванні
моделі (що означає обсяг пам'яті програм у кілобайтах) мають аналоги в се-
мействах Tiny та Mega. Для Mega під час програмування можливе встановлення спеці-
циального біта сумісності, який дозволяє без будь-яких змін вико-
користуватися програмами, створеними для сімейства Classic. Тому ряд прикладів у
цій книзі з метою спрощення викладу наводиться у версії для сімейства
Classic.
Приклади різних типів корпусів, у яких випускаються мікросхеми AVR,
наведено на рис. 1.1. Більш детальну інформацію на цю тему можна знайти у
додатку 1(табл. П1.2), а також у технічній документації на пристрої.
Зазначимо, що для радіоаматорських потреб та макетування найзручніше мікро-
схеми у PDIP-корпусах, але не всі моделі МК у таких корпусах виробляються.
Всі сімейства можуть мати дві модифікації: літера "L" у позначенні говорить
про розширений діапазон живлення 2,7-5,5 В, відсутність такої літери означає діа-
пазон живлення 4,5-5,5 В. При виборі конкретного типу мікросхеми потрібно бути
уважним, т. к. L-версії одночасно також і менш швидкодіючі, у
більшості їх максимальна тактова частота обмежена значенням 8 МГц.
Для " звичайних " версій максимальна частота становить 16 чи 20 МГц. Хоча як
правило, при запуску L-мікросхем з напругою живлення 5 на частотах до 10-
12 МГц неприємностей очікувати не слід (аналогічно версії без літери L цілком
можуть працювати при напрузі харчування близько 3 В, зрозуміло, не на екстремаль-
них значеннях частот), проте при проектуванні високонадійних вуст-
слід слід враховувати цю вимогу.
Мікросхеми Tiny мають Flash-ПЗУ програм об'ємом 1-8 кбайт і розміщуються в
здебільшого в корпусах з 8–20 висновками (крім ATtiny28), тобто вони загалом призначені.
призначені для більш простих та дешевих пристроїв. Це не означає, що їх можливо-
сті завжди обмежені, ніж у сімейства Mega. Так наприклад,
ATtiny26 при ціні менше 2 доларів містить таймер з високошвидкісним ШІМ-
режимом (в інших моделях такого немає), а також 11-канальний АЦП з мож-
ністю роботи в диференціальному режимі, з регульованим вхідним підсилювачем

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

і вбудованим джерелом опорної напруги, що характерно для старших мо-
справ. Мікросхема ATtiny2313, як уже говорилося, являє собою покращення.
ну версію одного з найбільш універсальних та зручних "класичних" AVR
AT90S2313.

Рис. 1.1.Приклади різних типів корпусів для МК AVR

Підсімейство Mega оснащене Flash-ПЗУ програм об'ємом 8–256 кбайт та корпу-
самі з 28-100 висновками. Загалом МК цієї групи більш "наворочені", ніж
Tiny, мають більш розгалужену систему вбудованих пристроїв з більш розвиненою
функціональністю.
Таблиці з основними характеристиками деяких моделей Tiny та Mega з числа
найбільш ходових наведено в додатку 1. Там же дано деякі загальні техні-
чеські характеристики сімейства AVR. Більш докладні відомості можна отримати.
нути з фірмової технічної документації, яка доступна на сайті
Atmel для кожної моделі.
Окрім цих трьох сімейств, на базі AVR-ядра випускаються спеціалізовані
мікросхеми для роботи з USB-інтерфейсом (AT90USB xxxx), промисловим ін-
терфейсом CAN (AT90CAN ххх), для управління РК-дисплеями (ATmega329 та ін.),
з бездротовим інтерфейсом IEEE 802.15.4 (ZigBee) для підприємств торгівлі та
деякі інші. Останнім часом деякі мікроконтролери серій Tiny та
Mega стали випускатися у версіях із надмалим споживанням (технологія
picoPower з напругою живлення від 1,8 В, наприкінці найменування МК цієї серії
додано літеру "P") та високотемпературних для використання в автомобільній
промисловості (версії Automotive). З'явилося сімейство XMega з напругою
живлення 1,8-3,6 В, підвищеною швидкодією (тактова частота до 32 МГц),

Розділ 1. Огляд мікроконтролерів Atmel AVR

12-розрядним 16-канальним АЦП та 2–4 каналами ЦАП (досі у структурі
AVR вони були відсутні), кількома каналами UART та інших послідовних
портів (причому з можливістю роботи в автономному режимі, при зупиненому
ядрі), вбудованою підтримкою криптографії, удосконаленим режимом
picoPower та іншими "наворотами". Існує також окреме сімейство 32-раз-
рядних МК AVR32, призначене для високошвидкісних додатків, таких
як обробка відеопотоку чи розпізнавання образів у часі.

Особливості
практичного використання МК AVR

При використанні AVR виникає низка питань практичного характеру, ігно-
рування яких може іноді призвести до непрацездатності або збоїв уст-
ройства (а деяких випадках - навіть до неможливості його запрограмувати).
Наприклад, однією з таких проблем є можливість втрати вмісту EEPROM
при вимиканні живлення. Цю та подібні проблеми ми докладно розглянемо у
відповідних розділах. Тут же зупинимося на деяких спільних питаннях
включення МК AVR.

Про споживання

МК AVR споживають у середньому 5-15 мА (без урахування споживання зовнішніх вуст-
рійств через висновки МК). Споживаний струм залежить не тільки від ступеня "на-
роченості" моделі, але й від тактової частоти та напруги живлення. На рис. 1.2
наведено типову діаграму залежності струму споживання від напруги пита-
ня та тактової частоти для молодших моделей сімейства Mega.
З рис. 1.2, зокрема, слід, що значно зменшити споживання можна,
знижуючи тактову частоту у тих випадках, коли час виконання програми не-
критично. Це дозволяє спростити програму, відмовившись від режимів енерго-
заощадження: наприклад, при встановленні "годинного" кварцу 32 768 Гц як так-
тируючого споживання МК може становити близько 200-300 мкА.

З

Амітки на полях

Величину струму споживання 1-2 мА і менше можна умовно вважати прийнятною для
батарейних пристроїв, які розраховані на довготривалий режим безперервної
роботи. Елементи типорозміру АА (типу alcaline, тобто лужні) мають ємність по-
рядка 2000 мА год, тобто пристрій із зазначеним споживанням від цих елементів про-
працює не менше 1000 год (реально навіть трохи більше) або понад 40 діб. Вре-
роботи від батарей типорозміру D з енергоємністю близько 15–18 000 мА год спів-
ставить близько року, чого більшості практичних застосувань достатньо.
Вибирати для живлення подібних пристроїв (особливо, що включаються періодично
на короткий час) слід саме лужні елементи, тому що вони мають великий
ємністю, не течуть при перерозряді і, головне, мають значно більший термін
зберігання (близько 7 років) проти іншими типами елементів.

Але уважний розгляд питання показує, що саме цим - спроще-
ням програми - у переважній більшості випадків переваги більш

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

низької тактової частоти та обмежуються. Графіки на мал. 1.2 лінійні, звідси
слід, що пропорційно зниженню тактової частоти зростає час виконання
ня команд. Таким чином, процедура, виконання якої при тактовій частоті
4 МГц займе 100 мкс, при тактовій частоті 32768 Гц триватиме більше 12 мс.
Легко підрахувати, що в тому та іншому випадку кількість енергії, спожитої на
виконання цієї процедури буде однаковим.

Рис. 1.2.Діаграма залежності струму споживання від напруги живлення

та тактової частоти для молодших моделей сімейства Mega

Тому можна зробити наступний загальний висновок: якщо ви не бажаєте вникати в
тонкощі режимів енергозбереження і не реалізуєте їх у програмі, то для загально-
го зниження споживання потрібно вибирати тактову частоту якомога нижче (на
практиці зазвичай досить обмежитися величиною 1 МГц, т. до.
зниження, швидше за все, не дасть ефекту через додаткове споживання внеш-
ними ланцюгами, що неминуче присутні у всіх схемах). Якщо ж у вас попереджу-
смотрен одне із режимів " глибокого " енергозбереження (див. розділ 4), то тактова
частота з погляду сумарного споживання мало значення.
Інша справа – вибір напруги живлення, яке бажано зробити як можна
менше, якщо це дозволяють зовнішні пристрої. Залежність струму споживання від
напруги живлення, як легко усвідомити графіки на рис. 1.2, нелінійна: з уве-
личенням напруги струм споживання швидко зростає. Тому знижувати на-
напруга живлення навіть з урахуванням обмеження на тактову частоту для більшості
моделей AVR (не більше 8 МГц при живленні 2,7 В) все одно вигідно. Наприклад,
пристрій з живленням 3 при тактовій частоті 8 МГц, згідно рис. 1.2, буде
споживати близько 3 мА або, у перерахунку на одиниці потужності, 9 мВт; на процедуру-

Розділ 1. Огляд мікроконтролерів Atmel AVR

ру тривалістю 100 мкс піде енергія 0,9 мкДж. При частоті 16 МГц та ж про-
цедура займе 50 мкс, але споживання при потрібній напрузі живлення 5 В
становитиме близько 14 мА, тобто 70 мВт; разом на виконання процедури піде енергія
3,5 мкДж, майже вчетверо більше.
Для всіх зовнішніх цифрових пристроїв, за рідкісним винятком, можна по-
добрати сучасний аналог, призначений для роботи при напругах 2,7-
3,0 (і навіть нижче, якщо модель контролера це дозволяє), так що з цього боку
обмежень немає; те, що більшість прикладів у цій книзі орієнтовано на
напруга живлення 5, є лише данина традиції. До того ж ці приклади, як
правило, мають на увазі харчування від мережі, де споживання не має великого зна-
чення. Лімітувати зниження напруги живлення можуть світлодіодні індикації.
тори (через те, що пряме падіння напруги на світлодіодах саме по собі
ставить порядку 2 В, а для великих індикаторів навіть 5 В для управління недостатньо
таточно), але в таких пристроях споживання контролера вже не грає великої
ролі: чотири семисегментні цифри самі по собі споживатимуть струм порядку
100 мА та більше. Інший випадок представляють аналогові схеми, де підвищення
напруги живлення вигідно з погляду збільшення відношення "сигнал-шум".
Зауважимо, що висновки AVR можуть у довготривалому режимі віддавати значний.
струм (до 20-40 мА), однак не слід забувати про загальне сумарне обмеження
на споживання з виведення живлення (див. . табл. П1.3). Слід також зазначити, що
при подачі аналогових напруг на входи АЦП вхідний цифровий КМОП-
елемент (вхід відповідного порту) не відключається, і при значенні даного
напруги поблизу порога спрацьовування елемента це може призводити до зростання.
танню споживання за рахунок протікання наскрізного струму через вихідні каскади
КМОП (у тому числі іноді і при знаходженні мікросхеми в "сплячому" режимі,
див. розділ 14). Цього недоліку позбавлені мікросхеми із технологією picoPower.

Деякі особливості застосування AVR у схемах

У більшості висновків МК є вбудований "підтягуючий"
(тобто приєднаний до шини живлення) резистор, що, здавалося б, вирішує одну з
звичайних схемотехнічних проблем, коли наявність такого резистора потрібна
для підключення двовивідних кнопок або виходів із "відкритим колектором".
Однак у критичних випадках необхідний зовнішній резистор опором 2-
5 кОм (у критичних для споживання випадках до 10-30 кОм).
"Підтягуючий" резистор слід встановлювати не тільки на виведенні /RESET
(про що йтиметься в главі 2), але й у тому випадку, коли висновки SCK, MOSI та MISO
відповідних портів використовуються для програмування та підключені до
програмуючому роз'єму ISP (див. розділ 5), а також за висновками зовнішніх прери-
вань, якщо вони задіяні. Якщо ці висновки не "підтягувати" до напруги
харчування додатковими резисторами (хоча це й не обумовлено в технічній
документації), то не виключені помилкові спрацьовування зовнішніх переривань, пе-
резапуск системи, а при дуже потужних перешкодах - навіть псування програми в пам'ять
ти програм. З іншого боку, коли висновки програмування служать і як-

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

сті звичайних портів, сконфігурованих на вихід, а у пристрої застосовуються
режими енергозбереження, наявність резисторів, що "підтягують", може привести
до зайвого споживання струму (при встановленні виведення в логічний нуль через рези-
стор потече струм від джерела живлення на вхід МК). Якщо реалізований один з ре-
жимов енергозбереження, то потрібно ретельно проаналізувати схему, щоб ви-
ключити ситуації, у яких через ці резистори протікає струм.
Також завжди слід встановлювати зовнішні резистори при роботі висновків МК на
загальну шину, як в інтерфейсі I

C (або просто при підключенні входу МК до

виходу іншого пристрою з відкритим колектором, наприклад, моніторів живлення.
ня, описаних у главі 3), при підключенні до двовивідних кнопок (особливо
за наявності зовнішнього переривання, див. глави 4і 5 ). Опір вбудованого
резистора (насправді представляє собою, зрозуміло, польовий транзистор)
у таких випадках занадто велике для того, щоб електромагнітні перешкоди ("на-
горілки") на ньому ефективно "сідали".
Мікросхеми AVR, як і будь-яка КМОП-логіка, завдяки високому порогу спра-
тиванії ефективно захищені від перешкод по шині "землі". Однак вони поводяться
набагато гірше при перешкодах по шині живлення. Тому не забувайте про розв'язування.
ших конденсаторах, які потрібно встановлювати безпосередньо у висновків пі-
танія (керамічні 0,1-0,5 мкФ), а також про якість мережевих випрямлячів і
стабілізаторів.

РОЗДІЛ

Загальний пристрій
організація пам'яті,
тактування, скидання

Загальна структура внутрішнього пристрою МК AVR наведена на рис. 2.1. На цій
схемою показані всі основні компоненти AVR (крім модуля JTAG);
в окремих моделях деякі складові можуть бути відсутніми або розрізняти-
ся за характеристиками, незмінним залишається лише загальне 8-розрядне процесор-
ядро (GPU, General Processing Unit). Коротко опишемо найважливіші компо-
енти, більшість з яких ми докладно розглядатимемо надалі.
Почнемо із пам'яті. У структурі AVR є три різновиди пам'яті: flash-
пам'ять програм, ОЗУ (SRAM) для тимчасових даних та енергонезалежна па-
м'ять (EEPROM) для довготривалого зберігання констант та даних. Розглянемо їх
окремо.

Пам'ять програм

Обсяг вбудованої flash-пам'яті програм в AVR-контролерах становить від
1 кбайт у ATtiny11 до 256 кбайт у ATmega2560. Перше число в найменуванні мо-
долі відповідає величині цієї пам'яті з ряду: 1, 2, 4, 8, 16, 32, 64, 128
256 кбайт. Пам'ять програм, як і будь-яка інша flash-пам'ять, має сторінку
організацію (розмір сторінки, залежно від моделі, становить від 64 до
256 байт). Сторінка може програмуватися лише повністю. Число циклів пе-
репрограмування сягає 10 тис.
З погляду програміста пам'ять програм можна вважати побудованою з від-
ділових осередків - слів по два байти кожне. Пристрій пам'яті програм (і тільки
цієї пам'яті) за двобайтовими словами - дуже важливий момент, який потрібно
твердо засвоїти. Така організація обумовлена ​​тим, що будь-яка команда в AVR
має довжину рівно два байти. Виняток становлять команди

і деякі-

інші (наприклад,

), які оперують з 16-розрядними і довшими-

ми адресами, довжина цих команд дорівнює чотирьом байтам і вони застосовуються лише
у моделях з пам'яттю програм об'ємом понад 8 кбайт (докладніше див. розділ 5). Во
у всіх інших випадках лічильник команд зсувається при виконанні чергового

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

команди на два байти (одне слово), тому необхідну ємність пам'яті легко
підрахувати, знаючи кількість використовуваних команд. Абсолютні адреси в пам'яті
грам (наведені, наприклад, у таблицях векторів переривань у технічному
опис МК) також відраховуються в словах.

Рис. 2.1.Загальна структурна схема мікроконтролерів AVR

З

Амітки на полях

Наведемо приклад цікавого випадку адресації, що представляє
команда для читання констант із пам'яті LPM (а також ELPM в МК з пам'яттю програм
128

кбайт і більше). Ця команда має на увазі читання з байтовомуадресою, вказаною-

ному у двох старших РОН (утворюють т. зв. регістр Z, див. далі). Проте щоб не
порушувати "чистоту" концепції організації пам'яті програм за словами, розробники
заплутали це просте питання, вказавши в описі, що при виклику команди LPM старий
ші 15 розрядів регістру Z адресують словоу пам'яті, а молодший розряд вибирає
молодший або старший байт (при рівності розряду 0 або 1 відповідно) цього

слова. Легко, однак, помітити, що байтова та послівна організація пам'яті при та-
кому підході еквівалентні.

Остання адреса наявного обсягу пам'яті програм для конкретної моделі
позначається константою

За замовчуванням усі контролери AVR завжди

починають виконання програми з адреси $0000. Якщо у програмі немає перерви-
ній, то з цієї адреси може починатися прикладна програма. У протилежному слу-

чаю за цією адресою розташовується т.з. таблиця векторів переривань, подробиць-
її про яку ми говоритимемо в розділах 4і 5 . Тут зазначимо лише, що першим у
цій таблиці (за тією ж адресою $0000) завжди розміщується вектор скидання

який вказує на процедуру, що виконується при скиданні МК (у тому числі
при включенні живлення).

П

РИМІТКА

В асемблері AVR можна позначати шістнадцяткові числа в "паскалівському"
стилі, випереджаючи їх знаком $, при цьому стиль мови С (0x00) теж дійсний, а ось
"інтелівський" спосіб (00h) не працює. Докладніше про позначення чисел різних
систем обчислення в AVR-ассемблері див. розділ 5.

В останніх адресах пам'яті програм контролерів сімейства Mega може розпо-
лагатися т.зв. завантажувач- спеціальна програма, яка керує завантаженням та
вивантаження прикладних програм з основного обсягу пам'яті. У цьому випадку по-
чення вектора скидання і всієї таблиці векторів переривань (тобто фактично на-
чального адреси, з якого починається виконання програми) може бути змі-
нено установкою спеціальних конфігураційних осередків (див. розділ 5).

Пам'ять даних (ОЗУ, SRAM)

На відміну від пам'яті програм адресний простір пам'яті даних адресується
побайтно (а чи не пословно). Адресація повністю лінійна, без якогось поділу
на сторінки, сегменти або банки, як це заведено в деяких інших системах.
Молодші МК сімейства Tiny (включаючи Tiny1 хі Tiny28) пам'яті даних, як тако-
виття, не мають, обмежуючись лише регістровим файлом (РОН) і регістрами ввій-
так-виводу (РВВ). В інших моделях обсяг вбудованої SRAM коливається від
128 байт у представниках сімейства Tiny (наприклад, у ATtiny2313) до 4–8 кбайт
у старших моделей Mega.
Адресний простір статичної пам'яті даних (SRAM) умовно поділяється на
кілька областей, показаних на рис. 2.2. Темною заливкою виділена частина, від-
що носиться до вбудованої SRAM, до неї по порядку адрес розташовує-
але адресний простір регістрів (перші 32 байти займає РОН, ще 64 -
РВВ). Для старших моделей Mega зі складною структурою (наприклад, ATmega128)
64-х регістрів введення-виведення може виявитися недостатньо, тому в них для до-
Додаткових РВВ виділяється окремий адресний простір (від $60 до максі-
мало можливого в байтовій адресації значення $FF, разом таких регістрів мо-
жет бути всього 160).

З

Амітки на полях

В архітектурі МК AVR поняття "введення-висновку" використовується у двох сенсах: по-

перше, є "порти вводу-виводу" (I/O ports), які ми розглянемо в главі 3.
По-друге, "регістром введення-виведення" (РВВ) в структурі AVR називаються регістри,
які забезпечують доступ до додаткових компонентів, зовнішніх щодо-

нію до GPU, за винятком ОЗУ (у тому числі і до портів введення-виводу). Таке під-
розподіл наближає структуру МК AVR до звичної конфігурації персонального
комп'ютера, де доступ до будь-яких зовнішніх по відношенню до центрального процесора
компонентів, крім пам'яті, здійснюється через порти вводу-виводу.

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

Для деяких моделей Mega (ATmega8515, ATmega162, ATmega128, ATmega2560
та ін) передбачена можливість підключення зовнішньої пам'яті обсягом до
64 кбайт, яка може бути будь-якою статичною
різновидом (SRAM, Flash або EEPROM) з па-
паралельним інтерфейсом.
Зазначимо, що адреси РОН та РВВ не забирають про-
мандрівка у ОЗУ даних (за винятком підклю-
зовнішньої пам'яті у старших моделей Mega,
максимальна адреса якої обмежена значенням
$FFFF): так, якщо в конкретній моделі МК є
512 байт SRAM, а простір регістрів займає
перші 96 байт (до адреси $60), то адреси SRAM
займуть адресний простір від $0060 до $025F
(тобто від 96-го до 607-го осередку включно). Кінець
вбудована пам'ять даних позначається константою

Рис. 2.2.Адресний простір

статичної пам'яті даних (SRAM)

мікроконтролерів AVR

Операції читання/запису на згадку однаково працюють з будь-якими адресами з дос-
тупного простору, і при роботі з SRAM потрібно бути уважним: замість
запису на згадку ви легко можете "потрапити" в якийсь регістр. Наприклад,
команда завантаження значення регістру

у регістр

) рівносильна

записи в SRAM за нульовою адресою (

). Адреса в пам'яті для РОН сов-

падає з його номером. У той же час для безпосереднього запису в РВВ за його
адресою в пам'яті до номера регістру слід додати $20: так, регістр прапорів

який для більшості моделей розташовується наприкінці таблиці РВВ за адресою
$3F, у пам'яті має адресу $5F. Встановлювати РОН та РВВ прямою адресацією па-
м'яти незручно: такий запис завжди забирає два такти замість одного, характерно.
го для більшості інших команд, хоча іноді це дозволяє обійти обмеження
на маніпуляції із деякими РВВ. Але якщо є готова програма, працюю-
щая з SRAM, то при заміні моделей процесорів на старші потрібно бути
уважним через те, що у них молодші адреси SRAM можуть перекриватися
додатковими РВВ.

Глава 2. Загальний пристрій, організація пам'яті, тактування, скидання

Енергонезалежна пам'ять даних (EEPROM)

Усі моделі МК AVR (крім знятого з виробництва ATtiny11) мають вбудовану
EEPROM для зберігання констант та даних при відключенні живлення.
У різних моделях об'єм її варіюється від 64 байт (ATtiny1х) до 4 кбайт (старші
моделі Mega). Кінець EEPROM позначається константою

(це позначить-

ня введено тільки для пізніших моделей AVR, тому при використанні
цієї константи іноді її доведеться визначати самому). Число циклів перепро-
грамування EEPROM може досягати 100 тис.
Нагадаємо, що EEPROM відрізняється від Flash можливістю вибіркового про-
грамування побайтно (в принципі навіть побітно, але цей спосіб недоступний
користувача). Однак у старших моделях сімейства EEPROM, як і flash-пам'ять
програм, що має сторінкову організацію, правда, сторінки ці невеликі - до
4 байти кожна. На практиці, як при програмуванні EEPROM по послідовно-
тельному каналу (тобто через SPI-інтерфейс програмування), так і при записі та
читанні EEPROM з програми, ця особливість не має значення, і доступ осу-
існує побайтно.
Читання з EEPROM здійснюється протягом одного машинного циклу (щоправда, на
практиці воно розтягується на чотири цикли, але програмісту слідкувати за цим спе-
циально не потрібно). А ось запис в EEPROM протікає значно повільніше,
і до того ж з точно не визначеною швидкістю: цикл запису одного байта може
займати від 2 до ~ 4 мс та більше. Процес запису регулюється вбудованим RC-
генератором, частота якого нестабільна (при нижчій напрузі живлення
очікується, що час запису буде більшим). За такий час при звичайних так-
тових частотах МК встигає виконати кілька тисяч команд, тому програм-
мування процедури запису вимагає акуратності: наприклад, потрібно стежити,
щоб у момент запису не "вклинилося" переривання (докладніше про це див. гла-
ви 4
і 9 ).
Головна ж складність при роботі з EEPROM - можливість пошкодження її спів-
держимого при недостатньо швидкому зниженні напруги живлення в момент
вимикання. Зумовлено це тим, що при зменшенні напруги живлення до
деякого порога (нижче порога стабільної роботи, але недостатнього для повно-
го виключення) через коливання напруги МК починає виконувати довіль-
команди, у тому числі може здійснити процедуру запису в EEPROM. Якщо
врахувати, що типова команда МК AVR виконується за десяті частки мікросекунди,
то ясно, що ніяке реальне джерело живлення не може забезпечити зниження
напруги до нуля за потрібний час За досвідом автора при харчуванні від звичайного
стабілізатора типу LM7805 з рекомендованими значеннями ємності конденсато-
рів на вході та на виході вміст EEPROM буде неминуче зіпсовано при-
мірно у половині випадків.
Ця проблема не повинна існувати, якщо константи записують в EEPROM
при програмуванні МК, а процедура запису у програмі відсутня (про те,
як сформувати файл з даними для EEPROM, див. розділ "Директиви та функці-
ції" глави 5
). Велика безпека даних у таких випадках підтверджується і ем-

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

піричними спостереженнями, і тим, що дозвіл запису в EEPROM - процедуру-
ра двоступінчаста (див. розділ 9). У всіх інших випадках (а їх, очевидно,
абсолютна більшість - в EEPROM найчастіше зберігають вуста-
новки та поточну конфігурацію при вимкненні живлення) доводиться приймати
спеціальні заходи. Найбільш кардинальною та універсальною з них є вуста-
новка зовнішнього монітора живлення, що утримує МК у стані скидання при
зменшення напруги живлення нижче граничної величини. Тієї ж мети служить
вбудований детектор падіння напруги (Brown-out Detection, BOD)
практично у всіх моделях Tiny і Mega, але технічна документація не виклю-
дає при цьому для надійності дублювання його та зовнішнім монітором живлення.
Докладніше про схему BOD та режими скидання МК див. далі в цьому розділі, а про програм-
му EEPROM та запобіжні заходи при її використанні див. розділ 9.

Способи тактування

Канонічний спосіб тактування МК - підключення кварцового резонатора
відповідним висновкам (рис. 2.3, а). Ємність конденсаторів С1 та С2 у типовому
у разі повинна становити 15–22 пФ (може бути збільшена до 33–47 пФ з одно-
тимчасовим підвищенням споживання). У більшості моделей Tiny і Mega мають-
ється спеціальний конфігураційний біт

Що дозволяє регулювати

споживання. При встановленні цього біта в 1 (незапрограмований стан)
розмах коливань генератора зменшується, проте при цьому звужується можливий
діапазон частот і загальна завадостійкість, тому задіяти цей режим
не рекомендується. Може бути вибраний низькочастотний кварцовий резонатор
(наприклад, "годинний" 32768 Гц), при цьому конденсатори С1 і С2 можуть відсут-
вати, тому що при установці

значення 0 підключаються наявні у складі

МК внутрішні конденсатори ємністю 36 пФ.
Кварцовий резонатор можна замінити на керамічне. Автору цих рядків вдавалося
запускати МК на нестандартних частотах, використовуючи замість кварцу в тому ж під-
ключенні мініатюрну індуктивність (при її значенні 4,7 мкГн та ємностях кон-
денсаторів 91 пФ частота виходить близько 10 МГц), що заразом дозволяє трохи
зменшити габарити схеми.
Звичайно, тактувати МК можна і від зовнішнього генератора (рис. 2.3, б). Осо-
це зручно, коли потрібно або синхронізувати МК із зовнішніми компо-
нентами, або отримати дуже точну частоту тактування, вибравши відповідн-
генератор (наприклад, серії SG-8002 фірми Epson).
Навпаки, коли точність не потрібна, можна підключити зовнішню RC-ланцюжок
(Рис. 2.3, в). У цій схемі ємність С1 має бути не менше 22 пФ, а резистор R1
вибирається з діапазону 3,3-100 кОм. Частота при цьому визначається за формулою
F= 2/3 RC. С1 можна не встановлювати взагалі, якщо записати балку. 0 у конфігура-
ційний осередок

Підключивши цим внутрішній конденсатор 36 пФ.

Нарешті, можна взагалі відмовитися від зовнішніх компонентів і обійтися
ним RC-генератором, який здатний працювати на чотирьох приблизних

Глава 2. Загальний пристрій, організація пам'яті, тактування, скидання

значеннях частот (1, 2, 4 та 8 МГц). У ряді моделей передбачена можливість
підстроювання частоти цього генератора (докладніше див. або технічний опис
конкретних моделей). Цю можливість найбільш доцільно використовувати в
молодших моделях Tiny, що випускаються у 8-контактному корпусі - тоді висновки,
призначені для підключення резонатора або зовнішнього генератора
задіяти інших цілей, як звичайні порти вводу-вывода.

Рис. 2.3.Способи тактування МК AVR з використанням: а- кварцового резонатора;

б- Зовнішнього генератора; в - RC-ланцюжки

Сімейство Classic вбудованого RC-генератора немає, а спеціальних конфігура-

ційних осередків у цих МК значно менше, і в загальному випадку на них можна не

звертати увагу. Для інших сімей це не так. За замовчуванням МК сімейства

Tiny і Mega встановлені в стан для роботи з вбудованим генератором
частоті 1 МГц (

0001), тому для інших режимів потрібно відповід-

щим чином встановити конфігураційні осередки

(Див. табл. 2.1). При цьому

слід враховувати, що стан осередків

0000 (дзеркальне по відношенню до

найбільш часто вживаному значенню для кварцового резонатора 1111) пере-

водить МК режим тактування від зовнішнього генератора, і навіть його не можна

навіть запрограмувати без подачі зовнішньої частоти. Про рекомендовані установи

ках конфігураційних осередків і про особливості їх програмування див.

розділ 5.

Таблиця 2.1.Установка конфігураційних осередків CKSEL

залежно від режимів тактування

CKSEL3...0

Джерело тактування

Частота

Зовнішня частота

Вбудований RC-генератор

Вбудований RC-генератор

Вбудований RC-генератор

Вбудований RC-генератор

Зовнішня RC-ланцюжок

Частина I. Загальні принципи пристрою та функціонування Atmel AVR

Таблиця 2.1(закінчення)

CKSEL3...0

Джерело тактування

Частота

Зовнішня RC-ланцюжок

0,9...3,0 МГц

Зовнішня RC-ланцюжок

3,0...8,0 МГц

Зовнішня RC-ланцюжок

8,0... 12 МГц

Низькочастотний резонатор

Кварцовий резонатор

0,4... 0,9 МГц

Кварцовий резонатор

0,9...3,0 МГц

Кварцовий резонатор

3,0...8,0 МГц

1ххх (CKPOT=0)

Кварцовий резонатор

Скидання

Скиданням (RESET) називається встановлення початкового режиму роботи МК. При цьому
всі РВВ встановлюються в стан за замовчуванням - як правило, це нулі
всіх розрядах, за невеликим винятком (а ось РОН можуть приймати вироб-
вільні значення, тому при необхідності починати з якоїсь певної
величини змінні слід встановлювати на початку програми (примусово).
Програма після скидання починає виконуватися з початкової адреси (за замовчуванням
це адреса $0000).
Скидання завжди відбувається при включенні живлення. Крім цього, джерелами сбро-
са можуть бути такі події: апаратне скидання, тобто подача низького рівня
напруги на вхід RESET (правильніше його позначати з інверсією: / RESET, т.к.
активний рівень тут низький, і ми дотримуватимемося цього правила); закінчу-
ня відліку встановленого інтервалу сторожового таймера; спрацювання схеми
BOD. Значення чотирьох молодших бітів регістру стану

повинно сигна-

лізувати про те, від якого джерела проводилося скидання попереднього разу (уста-
новка в 1 біта 0 - скидання при включенні, біта 1 - апаратне скидання, біта 2 - від
схеми BOD, біта 3 - від вартового таймера). На практиці, з досвіду автора,
станам цього регістру надійно відрізняються від інших лише состоя-
скидання по таймеру (інші прапори можуть виявитися встановленими все одно-
тимчасово). Проте ця інформація може бути корисною, наприклад, при аналізі
лізі причин перерв у роботі цілодобово працюючих пристроїв (див. розділ 12).
У молодших МК сімейства Tiny (крім ATtiny28) немає вбудованого "підтягуюче-
го" резистора на виведенні /RESET, тому для надійної роботи слід преду-
дивитися підключення зовнішнього резистора величиною 2–5 кОм від цього висновку
напруги живлення. Автор також рекомендує встановлювати по-
добний резистор для будь-яких моделей AVR, тому що вбудований резистор має бол-
шой номінал (100-500 кОм) і на ньому можуть наводитися перешкоди, здатні наважувати
ти до непередбачуваного скидання. Також (хоча в технічних описах такий реко-

Глава 2. Загальний пристрій, організація пам'яті, тактування, скидання

мендації і не міститься) не завадить установка конденсатора 0,1-0,5 мкФ від
виводу /RESET на "землю" - це згладжує неминучий брязкіт напруги і
трохи затягує фронт наростання напруги на виведенні /RESET порівняно
зі збільшенням напруги живлення: коли настане поріг спрацьовування схеми
скидання, напруга живлення всього МК вже встановиться.
У моделях Tiny, що випускаються у 8-контактному корпусі (ATtiny11–ATtiny15), є
Чи не потрібне зовнішнє скидання, висновок /RESET може виконувати функції звичайно-
го порту введення-виводу. З одним тільки нюансом: при конфігуруванні цього
контакту на вихід він працює, як висновок з відкритим колектором, а не як звичай-
логічний елемент (про конфігурацію висновків портів див. розділ 3).
Найкращий спосіб організації скидання при включенні живлення, як
вже говорилося раніше, - встановлення зовнішнього монітора живлення. Наприклад, при
5-вольтовому харчуванні підійде популярна мікросхема MC34064 з порогом спра-
тивання 4,6 В та типовим споживанням близько 300 мкА або її більш сучасний
аналог (наприклад, MAX803L із споживанням 12 мкА). Для тривольтного живлення
придатна схема MAX803R (2,6 В) або підходяща версія DS1816 з відповід-
щим напругою. Усі перелічені мікросхеми трививідні (живлення, "зем-
ля", виведення управління скиданням) і мають вихід з відкритим колектором, тобто пре-
Думають установку "підтягуючого" резистора. Типовий час спрацьовує-
ня цих мікросхем при зниженні напруги - мікросекунди, що забезпечує
збереження даних у EEPROM. У разі підвищення напруги вони забезпечують
велику тимчасову затримку (порядку часток секунди), що дозволяє надійно
здійснювати скидання МК без брязкоту.
Вбудована схема BOD забезпечує час спрацьовування порядку мікросекунд
затримкою на повернення в робочий стан після відновлення напруги, оп-
ределяющейся тими самими установками, як і затримка скидання (комірки

тактовій частоті 4 МГц) і навіть максимально можливе її значення ~68 мс можуть
виявитися недостатніми для обходу брязкоту, що виникає при зниженні на-
напруги живлення автономного джерела. Для вибору режиму роботи BOD слу-
жнив три конфігураційні осередки

мають такі стани:

111 (стандартна установка) - схема BOD вимкнена;

101 - включає BOD при порозі спрацьовування 2,7;

100 - відповідає порогу 4,0 Ст.

Зазначимо, що з точки зору надійності роботи, чим менша різниця між на-
напругою живлення та порогом спрацьовування монітора живлення (зовнішнього або
вбудованої схеми BOD, неважливо), тим краще - при невеликих стрибках харчування,
нечутливих для монітора, проте можуть відбуватися всілякі не-
приємності на кшталт мимовільного виникнення зовнішнього переривання. Одна-
до цієї різниці слід враховувати при живленні пристрою від батарей: наприклад,
для чотирьох "пальчикових" лужних акумуляторів і моніторі живлення, розрахун-
танном на 4,7 В, залишкова напруга на елементах після спрацьовування моніто-

Я не раз і не два говорив, що вивчення МК треба починати з асемблера. Цьому був присвячений цілий курс на сайті (щоправда, він не дуже послідовний, але поступово я його зачісую до адекватного вигляду). Так, це складно, результат буде не в перший день, зате ти навчишся розуміти що відбувається у тебе в контролері. Знатимеш як це працює, а не по мавпячому копіювати чужі вихідники і намагатися зрозуміти чому воно раптом перестало працювати. Крім того, Сі набагато простіше наробити бидлокода, який вилізе вилами в невідповідний момент.

На жаль, всі хочуть результат негайно. Тому я вирішив піти з іншого боку — зробити вправу по Сі, але з показом його спідньої білизни. Хороший програміст-ембеддер завжди міцно тримає свою заліза за шкварник, не даючи їй ні кроку ступити без дозволу. Так що буде спочатку Сі код, потім те, що народив компілятор і як все це працює насправді:)

З іншого боку, у Сі сильна сторона це переносимість коду. Якщо, звісно, ​​писати все правильно. Поділяючи алгоритми роботи та їх залізні реалізації у різні частини проекту. Тоді для перенесення алгоритму в інший МК достатньо переписати тільки інтерфейсний шар, де прописано все звернення до заліза, а весь робочий код залишити як є. І, звичайно ж, читання. Сишний вихідник простіше зрозуміти з першого погляду (хоча ... мені, наприклад, вже пофігу на що фтикати - хоч си, хоч асм:)), але, знову ж таки, якщо правильно все написати. Цим моментам я теж приділятиму увагу.

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

Перша програма на Сі для AVR

Вибір компілятора та встановлення середовища
Для AVR існує безліч різних компіляторів:
Насамперед це IAR AVR C- майже однозначно визнається найкращим компілятором для AVR, т.к. сам контролер створювався тісному співробітництві Atmel та спеців з IAR. Але за все доводиться платити. І цей компілятор мало того, що є дорогим комерційним софтом, так ще має такий прорив налаштувань, що просто взяти й скомпилити в ньому це треба постратися. У мене з ним правда не зрослося дружби, проект загнивав на дивних помилках на етапі лінківки (пізніше з'ясував, що це був кривий кряк).

Другим йде WinAVR GCC— потужний компілятор, що оптимізує. Повний опенсорц, кросплатформенний, загалом, усі радощі життя. Ще він відмінно інтегрується в AVR Studio дозволяючи вести налагодження прямо там, що дуже зручно. Загалом я вибрав його.

Також є CodeVision AVR C- дуже популярний компілятор. Став популярним у зв'язку зі своєю простотою. Робочу програму в ньому отримати можна вже через кілька хвилин - майстер стартового коду цьому дуже сприяє, штампуючи стандартині ініціалізації будь-яких уартів. Чесно кажучи, я якось з підозрою до нього ставлюся - якось раз доводилося дизасміти прогу написану цим компілером, каша якась а не код виходила. Жахлива кількість непотрібних рухів тіла і операцій, що виливалося в неслабкий обсяг коду і повільну швидкодію. Втім, можливо, тут була помилка в ДНК, який писав вихідну прошивку. Плюс, він хоче грошей. Не так багато, як IAR, але відчутно. А в деморежимі дає писати не більше ніж 2кб коду.
Кряк звичайно є, але якщо вже красти, то мільйон, у сенсі IAR:)

Ще є Image Craft AVR Cі MicroCвід мікроелектроніки Ні тим, ні іншим користуватися не доводилося, але ось SWGдуже вже нахвалює MicroPascal, мовляв, дуже зручне середовище програмування та бібліотеки. Думаю, MicroC не гірше буде, але теж платний.

Як я вже сказав, я вибрала WinAVRз трьох причин: халявний, інтегрується в AVR Studio і під нього написано просто прорив готового коду на всі випадки життя.

Так що качай собі інсталях WinAVR з і AVR Studio. Далі спочатку ставиться студія, потім зверху накочується WinAVR і чіпляється до студії у вигляді плагіна. Наполегливо рекомендую ставити WinAVR по короткому шляху, що на кшталт C:\WinAVR тим самим ти уникнеш купи проблем з шляхами.

Створення проекту
Отже, студія поставлена, Сі прикручений, пора б і спробувати щось запрограмувати. Почнемо з простого, найпростішого. Запускай студію, вибирай там новий проект, як компілятор AVR GCC і вписуй назву проекту.

Відкривається робоче поле з порожнім файлом *.c.

Тепер не завадить настроїти відображення шляхів у закладках студії. Для цього злазь за адресою:
Меню Tools - Options - General - FileTabs і вибираємо у списку «Filename Only». Інакше працювати буде неможливо - на вкладці буде повний шлях файлу, і на екрані буде не більше двох трьох вкладок.

Налаштування проекту
Взагалі, класичним вважається створення make файлу в якому були б описані всі залежності. І це, мабуть, правильно. Але мені, який виріс на повністю інтегрованих IDE начебто uVisionабо AVR Studioцей підхід є глибоко далеким. Тому робитиму за своїм, усе засобами студії.

Тикай у кнопку з шестернею.


Це налаштування твого проекту, а точніше, налаштування автоматичної генерації make файлу. На першій сторінці треба лише вписати частоту на якій буде працювати твій МК. Це залежить від фьюз бітів, так що вважаємо, що частота у нас 8000000Гц.
Також зверніть увагу на рядок оптимізації. Зараз там стоїть -Os це оптимізація за розміром. Поки залиш як є, потім можеш спробувати погратися з цим параметром. -O0 це відсутність оптимізації взагалі.

Наступним кроком буде налаштування шляхів. Насамперед додай туди директорію твого проекту — туди підкладатимеш сторонні бібліотеки. У списку з'явиться шлях "."

Make файл згенерований, його ти можеш подивитися в папці default у своєму проекті, просто пробіг очима, подивися що там є.


На цьому поки що все. Тисни скрізь ОК і переходь у вихідник.

Постановка задачі
Чистий лист так і підмиває втілити якусь хитру задумку, так як банальне миготіння діодом вже не вставляє. Давай вже відразу брати бика за роги і реалізуємо зв'язок з комп'ютером - це насамперед що я роблю.

Працюватиме так:
При приході по COM порту одиниці (код 0х31) запалюватимемо діодік, а при приході нуля (код 0х30) гасити. Причому зроблено все на перериваннях, а фоновим завданням буде миготіння іншого діода. Просто і з сенсом.

Збираємо схему
Нам треба з'єднати модуль USB-USART конвертера з висновками USART мікроконтролера. Для цього беремо перемичку з двох проводків і накидаємо на штирьки навхрест. Тобто Rx контролера з'єднуємо з Tx конвертер, а Tx конвертер з Rx контролера.

Вийде, у результаті ось така схема:


Підключення решти висновків, живлення, скидання не розглядаю, воно стандартне

Пишемо код

Відразу обмовлюся, що я не заглиблюватимусь конкретно в опис самої мови Сі. Для цього існує колосальна кількість матеріалу, починаючи від класики «Мова програмування Сі» від K&R і закінчуючи різними методичками.

Одна така методу знайшлася у мене в загашнику, я колись саме по ній вивчав цю мову. Там все коротко, зрозуміло та у справі. Я її поступово верстаю та перетягую на свій сайт.

Там, правда, ще не всі глави перенесені, але, думаю, це ненадовго.

Навряд чи я опишу краще, тому з навчального курсу, замість докладного роз'яснення сишних тонкощів, я просто даватиму прямі лінки на окремі сторінки цієї методички.

Додаємо бібліотеки.
Насамперед ми додаємо потрібні бібліотеки та заголовки з визначеннями. Адже Сі це універсальна мова і йому треба пояснити, що ми працюємо саме з AVR, так що вписуй у вихідний рядок:

1 #include

#include

Цей файл знаходиться в папці WinAVRі в ньому міститься опис усіх регістрів та портів контролера. Причому там все хитро, з прив'язкою до конкретного контролера, який передається компілятором через makeфайл у параметрі MCUі на підставі цієї змінної у твій проект підключається заголовний файл з описом адрес всіх портів і регістрів саме на цей контролер. Ось як! Без нього теж можна, але тоді ти не зможеш використовувати символічні імена регістрів на кшталт SREG або UDR і доведеться пам'ятати адресу кожного на кшталт «0xC1», а це зламати голову.

Сама ж команда #include<имя файла> дозволяє додати у твій проект вміст будь-якого текстового файлу, наприклад файл з описом функцій або шматок іншого коду. А щоб директива могла цей файл знайти ми та вказували шляхи до нашого проекту (директорія WinAVR там вже за дефолтом прописана).

Головна функція.
Програма мовою Сі вся складається з функцій. Вони можуть бути вкладеними та викликатися один з одного у будь-якому порядку та різними способами. Кожна функція має три обов'язкові параметри:

  • Значення, що повертається, наприклад, sin(x)повертає значення синусу ікс. Як у математиці, коротше.
  • Параметри, що передаються, цей ікс.
  • Тіло функції.

Усі значення передані і повертаються мають бути якогось типу, залежно від даних.

Будь-яка програма на Сі повинна містити функцію mainяк точку входу в головну програму, інакше це ніфіга не Сі:). За наявності main в чужому вихіднику з мільйона файлів можна зрозуміти, що це і є головна частина програми, звідки починається все. Ось і поставимо:

1 2 3 4 5 int main (void) (return 0;)

int main(void) ( return 0; )

Все, перша найпростіша програма написана, не біда, що вона нічого не робить, ми ж тільки почали.

Розберемо що ми зробили.
intце тип даних, яка функція main повертає.

Звичайно, у мікроконтролері mainнічого повернути в принципі не може і за ідеєю має бути void main(void), але GCC спочатку заточений на PC і там програма може повернути значення операційної системи після завершення. Тому GCC на void main(void)лається Warning'ом.

Це не помилка, працювати буде, але я не люблю варнінги.

voidце тип даних, які ми передаємо в функцію, в даному випадку mainтакож не може нічого прийняти ззовні, тому void- Пустушка. Заглушка, застосовується тоді, коли не треба нічого передавати або повертати.

Ось такі ось { } фігурні дужки це програмний блок, в даному випадку тіло функції main, там буде розміщуватися код.

return— це значення, що повертається, яке функція main віддасть при завершенні, оскільки у нас int, тобто число, то повернути ми повинні число. Хоча це однаково немає сенсу, т.к. на мікроконтролері з main нам виходити хіба що нікуди. Я повертаю нуль. Бо нефіг. А компілятор зазвичай розумний, і на цей випадок код не генерує.
Хоча, якщо перекрутитися, то з mainна МК вийти можна - наприклад вивалитися в секцію бутлоадера і виконати її, але вже потрібно низькорівневе колупання прошивки, щоб підправити адреси переходу. Нижче ти сам побачиш і зрозумієш, як це зробити. Навіщо? Ось це вже інше питання, у 99.999% випадків це нафіг не треба:)

Зробили, поїхали далі. Додамо змінну, вона нам не особливо потрібна і без потрібні вводити змінні не варто, але ж ми вчимося. Якщо змінні додаються всередині тіла функції, то вони локальні і існують тільки в цій функції. Коли з функції виходиш ці змінні віддаляються, а пам'ять ОЗУ віддається під найважливіші потреби. .

1 2 3 4 5 6 int main(void ) ( unsigned char i; return 0 ; )

int main(void) ( unsigned char i; return 0; )

unsignedзначить беззнаковий. Справа в тому, що в двійковому поданні у нас старший біт відводиться під знак, а значить, в один байт (char) влазить число +127/-128, але якщо знак відкинути то влізе вже від 0 до 255. Зазвичай знак не потрібен. Так що unsigned.
i— це лише ім'я змінної. Не більше того.

Тепер треба проініціалізувати порти та UART. Звичайно, можна взяти і підключити бібліотеку і викликати якийсь UartInit (9600); але тоді ти не дізнаєшся, що сталося насправді.

Робимо так:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void ) ( unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) ( unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO(bauddivider); UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 1<

Страшна? Насправді реалного коду тут лише п'ять останніх рядків. Все, що #defineце макромова препроцесора. Майже те ж бадилля, що і в Ассемблері, але синтаксис трохи інший.

Вони полегшать твої рутинні операції щодо обчислення потрібних коефіцієнтів. У першому рядку ми говоримо, що замість XTALможна сміливо підставляти 8000000, а L- Вказівка ​​типу, мовляв long - це тактова частота процесора. Теж саме baudrate- Частота передачі даних по UART.

bauddividerвже складніше, замість нього буде підставлятися вираз обчислений за формулою двох попередніх.
Ну а LOі HIна цьому результату візьмуть молодший і старший байти, т.к. в один байт воно може не влізти. В HIробиться зсув ікса (вхідний параметр макросу) вісім разів направо, у результаті від нього залишиться лише старший байт. А в LOми робимо побітове І з числом 00FF, в результаті залишиться лише молодший байт.

Так що все, що зроблено як #defineможна сміливо викинути, а потрібні числа підрахувати на калькуляторі і відразу вписати їх у рядки UBBRL = …. та UBBRH = …..

Можна, можливо. Але! Робити цього КАТЕГОРИЧНО НЕ МОЖНА!

Працюватиме і так і так, але в тебе в програмі з'являться так звані магічні числа— значення взяті незрозуміло звідки й незрозуміло навіщо і якщо ти через пару років відкриєш такий проект, то зрозуміти що це за значення буде дуже важко. Та й зараз, захочеш ти змінити швидкість, або поміняєш частоту кварцу і все доведеться перераховувати наново, а так поміняв пару циферок у коді і все саме. Загалом, якщо не хочеш уславитися бидлокодером, то роби код таким, щоб він легко читався, був зрозумілий і легко модифікувався.

Далі все просто:
Всі ці «UBRRL і З» це регістри конфігурації UART передавача за допомогою якого ми спілкуватимемося зі світом. І зараз ми надали їм потрібні значення, налаштувавши на потрібну швидкість і потрібний режим.

Запис виду 1<означає наступне: взяти 1 і поставити її на місце RXENу байті. RXENце 4й біт регістру UCSRB, так що 1<утворює двійкове число 00010000, TXEN— це третій біт, а 1<дасть 00001000. Одиночна "|" це побітове АБО, отже 00010000 | 00001000 = 00011000. Таким же чином виставляються і додаються в загальну купу інші необхідні біти конфігурації. У результаті зібране число записується в UCSRB. Докладніше розписано в дататі на МК в розділі USART. Тож не відволікаємось на технічні деталі.

Готово, настав час подивитися що вийшло. Тисніть на компіляцію та запуск емуляції (Ctrl+F7).

Налагодження
Пробігли всілякі прогреси, студія змінилася і біля входу в функцію main з'явилася жовта стрілочка. Це де процесор в даний момент, а симуляція на паузі.

Справа в тому, що спочатку, насправді, вона стояла на рядку UBRRL = LO (bauddivider); Адже те, що у нас у define це не код, а просто попередні обчислення, ось симулятор трохи і затупив. Але тепер він усвідомив, першу інструкцію виконано і якщо ти залізеш у дерево I/O View, в розділ USART і подивишся там на байт UBBRL то побачиш, що там значення вже є! 0х33.

Зроби ще один крок. Подивись як зміниться вміст іншого регістру. Так пройди їх усі, зверни увагу на те, що всі зазначені біти виставляються як я тобі і говорив, причому виставляються одночасно для всього байта. Далі Return справа не піде – програма скінчилася.

Розтин
Тепер скинь симуляцію у нуль. Натисніть там Reset (Shift+F5). Відкривай дизассембльований лістинг, зараз ти побачиш, що відбувається в контролері насправді. View -> Disassembler. І не ЫЫАААА! Асемблер! ЖАХ!!! А ТРЕБА. Щоб потім, коли щось піде не так, не тупив у код і не ставив ламерських питаннях на форумах, а одразу ж ліз у тельбухи і дивився де в тебе затик. Нічого страшного там немає.

Спочатку буде бадилля із серії:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A СПМ 0x0000002A Перейти +00000002: 940C0034 СПМ 0x00000034 Перейти +00000004: 940C0034 СПМ 0x00000034 Перейти +00000006: 940C0034 СПМ 0x00000034 Перейти +00000008: 940C0034 СПМ 0x00000034 Перейти + 0000000A: 940C0034 СПМ 0x00000034 Перейти + 0000000C: 940C0034 СПМ 0x00000034 Перейти + 0000000E: 940C0034 СПМ 0x00000034 Перейти +00000010: 940C0034 СПМ 0x00000034 Перейти +00000012: 940C0034 СПМ 0x00000034 Перейти +00000014: 940C0034 СПМ 0x00000034 Перейти +00000016: 940C0034 СПМ 0x00000034 Перейти +00000018: 940C0034 СПМ 0x00000034 Перейти + 0000001a: 940C0034 СПМ 0x00000034 Перейти + 0000001C : 940C0034 СПМ 0x00000034 Перейти + 0000001E: 940C0034 СПМ 0x00000034 Перейти +00000020: 940C0034 СПМ 0x00000034 Перейти +00000022: 940C0034 СПМ 0x00000034 Перейти +00000024: 940C0034 СПМ 0x00000034 Перейти +00000026: 940C0034 СПМ 0x00000034 Перейти +00000028: 940C0034 СПМ 0x00000034 Перейти

00000000: 940C002A СПМ 0x0000002A Перейти +00000002: 940C0034 СПМ 0x00000034 Перейти +00000004: 940C0034 СПМ 0x00000034 Перейти +00000006: 940C0034 СПМ 0x00000034 Перейти +00000008: 940C0034 СПМ 0x00000034 Перейти + 0000000A: 940C0034 СПМ 0x00000034 Перейти + 0000000C: 940C0034 СПМ 0x00000034 Перейти + 0000000E : 940C0034 СПМ 0x00000034 Перейти +00000010: 940C0034 СПМ 0x00000034 Перейти +00000012: 940C0034 СПМ 0x00000034 Перейти +00000014: 940C0034 СПМ 0x00000034 Перейти +00000016: 940C0034 СПМ 0x00000034 Перейти +00000018: 940C0034 СПМ 0x00000034 Перейти + 0000001a: 940C0034 СПМ 0x00000034 Перейти + 0000001C: 940C0034 СПМ 0x00000034 Перейти + 0000001E: 940C0034 СПМ 0x00000034 Перейти +00000020: 940C0034 СПМ 0x00000034 Перейти +00000022: 940C0034 СПМ 0x00000034 Перейти +00000024: 940C0034 СПМ 0x00000034 Перейти +00000026: 940C0034 СПМ 0x00000034 Перейти +00000028: 940C0034 СПМ 0x00000034 Перейти

Це таблиця векторів переривань. До неї ми ще повернемося, поки просто подивися і запам'ятай, що вона є. Перша колонка - адреса осередку флешу в якій лежить команда, друга код команди третя мнемоніка команди, та сама асемблерна інструкція, третя операнди команди. Та й автоматичний комент.
Так ось, якщо ти подивишся, то тут суцільні переходи. А код команди JMP чотирьох байтний, у ньому міститься адреса переходу, записана задом наперед - молодший байт за молодшою ​​адресою та код команди переходу 940C

0000002B: BE1F OUT 0x3F,R1 Out to I/O location

Запис цього нуля на адресу 0x3F, Якщо ти подивишся в колонку I/O view, то побачиш що адреса 0x3F це адреса регістру SREG — прапорового регістру контролера. Тобто. ми обнулюємо SREG, щоб запустити програму на нульових умовах.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Load immediate +0000002D: E0D4 LDI R29,0x04 Load immediate

0000002C: E5CF LDI R28,0x5F Load immediate +0000002D: E0D4 LDI R29,0x04 Load immediate +0000002E: BFDE OUT 0x3E,R29 I/O location +00000002

Це завантаження вказівника стека. Безпосередньо вантажити в I/O регістри не можна, тільки через проміжний регістр. Тому спочатку LDI проміжний, а потім звідти OUT в I/O. Про стеку я також розповім докладніше. Поки знай, що це така динамічна область пам'яті, висить наприкінці ОЗУ і зберігає в собі адреси та проміжні змінні. Ось зараз ми вказали на те, звідки у нас починатиметься стек.

00000032: 940C0041 JMP 0x00000041 Jump

Стрибок у сааааамий кінець програми, а там у нас заборона переривань та зациклювання наглухо саме на себе:

1 2 +00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relative jump

00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relative jump

Це випадок непередбачених обставин, наприклад виходу з функції main. З такого зациклювання контролер можна вивести або апаратним скиданням, або, що найімовірніше, скиданням від сторожового собаки - watchdog. Ну або, як я говорив вище, підправити це місць у хекс редакторі і поїхати куди нам душі завгодно. Також зверніть увагу на те, що буває два типи переходів JMP і RJMP – перший це прямий перехід за адресою. Він займає чотири байти і може зробити прямий перехід по всій області пам'яті. Другий тип переходу – RJMP – відносний. Його команда займає два байти, але перехід він робить від поточного положення (адреси) на 1024 кроки вперед або назад. І його параметрах вказується зміщення від поточної точки. Використовується найчастіше, т.к. займає вдвічі менше місця у флеші, а довгі переходи потрібні рідко.

1 +00000034: 940C0000 JMP 0x00000000 Jump

00000034: 940C0000 JMP 0x00000000 Jump

А це стрибок на початок коду. Перезавантаження свого роду. Можеш перевірити, чи всі вектори стрибають сюди. З цього висновок — якщо ти зараз дозволиш переривання (вони за дефолтом заборонені) і в тебе переривання пройдеться, а обробника немає, то програмне скидання — програму кине на самий початок.

функція main. Все аналогічно навіть можна і не описувати. Подивися щойно до регістру заноситься вже обчислене число. Препроцесор компілятора рулить! Тож жодних «магічних» чисел!

1 2 3 4 5 6 7 8 9 10 11 12 <

00000036: E383 LDI R24,0x33 Load immediate +00000037: B989 OUT 0x09,R24 Перейти до I/O location 15: UBRRH = HI(bauddivider); +00000038: BC10 OUT 0x20,R1 Перейти до I/O location 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Перейти до I/O location 17: UCSRB = 1<

А ось тут косяк:

1 2 3 +0000003E: E080 LDI R24,0x00 Load immediate +0000003F: E090 LDI R25,0x00 Load immediate +00000040: 9508 RET Subroutine return

0000003E: E080 LDI R24,0x00 Load immediate +0000003F: E090 LDI R25,0x00 Load immediate +00000040: 9508 RET Subroutine return

Постає питання, навіщо це компілятор додає таке бадилля? А це не що інше, як Return 0, функцію ми визначили як int main(void) ось і просрали ще цілих чотири байти не зрозумій на що:) А якщо зробити void main(void) то залишиться тільки RET, але з'явиться варнінг, що мовляв, у нас функція main нічого не повертає. Загалом, роби як хоч:)

Важко? Начебто ні. Пощелкай покрокове виконання в режимі дизассемблера і позир як процесор виконує окремі інструкції, що при цьому відбувається з регістрів. Як відбувається переміщення по командах та підсумкове зациклювання.

Продовження слідує через пару днів.

Offtop:
Alexei78зварганив плагінчик для файрфокса, що полегшує навігацію по моєму сайту та форуму.
Обговорення та скачування,

Принципова схема програматора на порт LPT показана на малюнку. Як шинний формувач використовуйте мікросхему 74AC 244 або 74HC244 (К1564АП5), 74LS244 (К555АП5) або 74ALS244 (К1533АП5).

Світлодіод VD1 індикує режим запису мікроконтролера,

світлодіод VD2 - читання,

світлодіод VD3 – наявність живлення схеми.

Напруга, необхідне харчування схема бере з роз'єму ISP, тобто. від програмованого пристрою. Ця схема є переробленою схемою програматора STK200/300 (додані світлодіоди для зручності роботи), тому вона сумісна з усіма програмами програматорів на PC, що працюють зі схемою STK200/300. Для роботи з цим програматором використовуйте програму CVAVR

Програматор можна виконати на друкованій платі та помістити її в корпус роз'єму LPT, як показано на рисунках:




Для роботи з програматором зручно використовувати подовжувач LPT порту, який легко виготовити самому (наприклад, з кабелю Centronix для принтера), головне "не шкодувати" провідників для землі (18-25 ноги роз'єму) або купити. Кабель між програматором та програмованою мікросхемою не повинен перевищувати 20-30 см.


Сучасне радіоаматорство неможливо уявити без мікроконтролерів, і це очевидно. В останні десятиліття мікроконтролери різних виробників стали широко поширені у різних сферах діяльності. Нерідко їх можна зустріти в найнесподіваніших пристроях та конструкціях. Ми з вами є свідками комп'ютеризації та автоматизації навколишніх нас процесів. Істина така, що без знання основ програмування створювати сучасні конкурентоспроможні пристрої стало практично неможливо.

Якщо ви читаєте цю статтю, можливо у вас виникло бажання зрозуміти, як працюють мікроконтролери, і швидше за все постали питання:

4. Яку літературу вивчати?

Спробуємо відповісти на ці запитання.

1. Який мікроконтролер вибрати для роботи?

Великою популярністю у радіоаматорів користуються 8-бітові мікроконтролери PICфірми Microchip Technology та AVRфірми Atmel, 16-бітні MSP430фірми TI, а також 32-бітні мікроконтролери, архітектури ARM.

У промисловості, дещо інакше, перше місце з великим відривом посідає Renesas Electronicsна другому Freescale, на третьому Samsungпотім йдуть Microchipі TI, далі всі інші.
Популярність визначається ціною та доступністю, чималу роль відіграють наявність технічної інформації та вартість програмного супроводу.

Ми вивчатимемо 8-бітні мікроконтролери AVR, сімейства ATMEGA 8 та 16 серії. Вибір визначився, знову ж таки доступністю, наявністю безлічі аматорських розробок, величезною кількістю навчального матеріалу. Наявністю різноманітних вбудованих компонентів та функціональністю цього сімейства.

2. Яке середовище розробки для програмування вибраного мікроконтролера?

Для AVR створено різні інтегровані середовища розробки (IDE, Integrated development environment).
IDE– це система програмних засобів, що використовується програмістами для розробки програмного забезпечення (ПЗ), до складу якої входять:
текстовий редактор,
компілятор та/або інтерпретатор,
засоби автоматизації збирання,
відладчик.

Найбільш поширені з них AVRStudio, ATmelStudio, WINAVR, CodeVision, IAR Embedded Workbench.
Для того, щоб писати програми, ми скористаємося безкоштовною IDE ATmelStudio версії 6і вище.
Завантажити Atmel Studio можна з офіційного сайту після реєстрації (реєстрація абсолютно безкоштовна і нічого не зобов'язує!)

ATmelStudio дозволяє створювати проекти і писати програми як в асемблері, так і на СІ.

Спочатку завжди постає питання: яку мову програмування вибрати, щоб писати ефективні програми?

Відповім просто: потрібно вміти писати як мінімум двома мовами асемблері та СІ. Асемблер просто необхідний, коли потрібно написати швидкі та компактні підпрограми та макроси, різні драйвери пристроїв. Але, коли потрібно створити об'ємний проект, побудований на складних алгоритмах, без знання СІ може бути витрачено дуже багато часу, особливо в процесі налагодження, а якщо виникне бажання перенести на іншу платформу, наприклад PIC18 або STM, може стати нерозв'язною проблемою.
Окрім цього, зараз з'явилися апаратні обчислювальні платформи Arduino, робота з якими вимагає знання мови СІ++
Тому писатимемо програми як в асемблері, так і на СІ.

Щоб наочно бачити результат своєї роботи, не використовуючи паяльник чи макетну плату, достатньо встановити програму Proteus.

3. Як прошивати контролер і які додаткові прилади та аксесуари потрібні для зручної роботи з ними?

Використовуємо датагорську. Крім цього, потрібно буде придбати макетні плати, блок живлення із вихідною напругою 5 Вольт. Можна як БП з малими пульсаціями використовувати, застосувавши стабілітрон на 5 Вольт.
Можливо, згодом ми з Ігорем запропонуємо проект для складання налагоджувальної плати.

4. Яку літературу вивчати?

А ось, наприклад:
Практичне програмування AVR на асемблері. Ревич, 2011
1000 та одна мікроконтролерна схема Вип. 1-2. Рюмік, 2010-2011
10 практичних пристроїв на МК AVR Книга 1-2. Кравченка, 2008-2009
Самовчитель розробника пристроїв на МК AVR. Бєлов, 2008
МК AVR сімейств Tiny та Atmega. Єфстіфєєв, 2008
CodeVisionAVR. Посібник для початківців. Лебедєв, 2008
Мікропроцесорне керування пристроями, тиристори, реле. Бєлов, 2008
Аналогові інтерфейси МК. Стюард, Болл, 2007
Створюємо пристрої на МК AVR. Бєлов, 2007
МК AVR у радіоаматорській практиці. Повний аналіз ATTINY2313. Бєлов, 2007
Мережевий та міжмережевий обмін даними з МК. Іди, 2007
МК AVR. практикум для початківців. Хартів, 2007
Схеми, алгоритми, програми. Баранів, 2006
Мікроконтролери AVR. Вступний курс. Мортон, 2006
Вимірювання, керування та регулювання за допомогою AVR. Трамперт, 2006
Програмування мовою С для AVR та PIC МК. Шпак, 2006
Конструювання пристроїв на МК. Бєлов, 2005
МK - це просто, томи 1-3. Фрунзе, 2002-2003
Мова програмування Сі, 2-ге видання. Керніган, Рітчі, 2009
Програмування мікроконтролерів ATMEL мовою С. Прокопенко, 2012

5. Де в інтернеті можна ставити запитання та отримувати конкретні відповіді?

Задавати питання ви можете на нашому або будь-якому іншому форумі, де так чи інакше торкнулися теми з мікроконтролерів. Головне на форумах правильно формулювати питання, щоб чітко отримувати відповіді. Абстрактні питання не вітаються, і швидше за все замість відповіді ви отримаєте жорстку критику, або ваше питання залишиться поза увагою!

Тепер розглянемо ближче нашого лідера, мікроконтролер ATMEGA 8

8-розрядний високопродуктивний AVR мікроконтролер із малим споживанням
Прогресивна RISC архітектура
130 високопродуктивних команд, більшість команд виконується за один тактовий цикл
32 8-розрядних робітників регістру загального призначення
Повністю статична робота
Наближається до 16 MIPS (при тактовій частоті 16 МГц) продуктивність
Вбудований 2-цикловий перемножувач

Енергонезалежна пам'ять програм та даних
8 Кбайт внутрішньосистемно програмованої Flash пам'яті (In-System Self-Programmable Flash)
Забезпечує 1000 циклів стирання/запису
Додатковий сектор завантажувальних кодів із незалежними бітами блокування
Забезпечено режим одночасного читання/запису (Read-While-Write)
512 байт EEPROM
Забезпечує 100000 циклів стирання/запису
1 Кбайт вбудованої SRAM
Програмоване блокування, що забезпечує захист програмних засобів користувача

Вбудована периферія
Два 8-розрядні таймери/лічильники з окремим попереднім дільником, один з режимом порівняння
Один 16-розрядний таймер/лічильник з окремим попереднім дільником та режимами захоплення та порівняння
Лічильник реального часу з окремим генератором
Три канали PWM
8-канальний аналого-цифровий перетворювач (у корпусах TQFP та MLF)
6 каналів із 10-розрядною точністю
6-канальний аналого-цифровий перетворювач (у корпусі PDIP)
4 канали з 10-розрядною точністю
2 канали з 8-розрядною точністю
Байт-орієнтований 2-провідний послідовний інтерфейс
Програмований послідовний USART
Послідовний інтерфейс SPI (провідний/відомий)
Програмований сторожовий таймер з окремим вбудованим генератором
Вбудований аналоговий компаратор

Спеціальні мікроконтролерні функції
Скидання подачі живлення та програмований детектор короткочасного зниження напруги живлення
Вбудований калібрований RC-генератор
Внутрішні та зовнішні джерела переривань
П'ять режимів зниженого споживання: Idle, Power-save, Power-down, Standby та зниження шумів ADC

Висновки I/O та корпуси
23 програмовані лінії введення/виводу
28-вивідний корпус PDIP, 32-вивідний корпус TQFP та 32-вивідний корпус MLF

Робоча напруга
2,7 - 5,5 В (ATmega8L)
4,5 - 5,5 В (ATmega8)

Робоча частота
0 - 8 МГц (ATmega8L)
0 – 16 МГц (ATmega8)

відмінності ATMEGA16 від 8
16 Кбайт внутрішньосистемно програмованої Flash пам'яті (In-System Self-Programmable Flash)

Інтерфейс JTAG (сумісний із IEEE 1149.1)
Можливість сканування периферії, що відповідає стандарту JTAG
Розширена підтримка вбудованого налагодження
Програмування через JTAG інтерфейс: Flash, EEPROM пам'яті, перемичок та бітів блокування

Чотири канали PWM / ШИМ

8-канальний 10-розрядний аналого-цифровий перетворювач
8 несиметричних каналів
7 диференціальних каналів (тільки у корпусі TQFP)
2 диференціальних канали з програмованим посиленням 1, 10 або 200 крат (тільки в корпусі TQFP)

Шість режимів зниженого споживання: Idle, Power-save, Power-down, Standby, Extended Standby та зниження шумів ADC

32 програмовані лінії введення/виводу

40-вивідний корпус PDIP та 44-вивідний корпус TQFP

AtmelStudio

Якщо Ви тільки починаєте, то потрібно завантажити та встановити програму AtmelStudio з офіційної сторінки atmel.com
Після встановлення програми AtmelStudio можна розпочати створення проекту.
Проект– це ваша програма, яку ви писатимете, налагоджуватимете і прошиватимете, після компіляції, на згадку про мікроконтролер.

Щоб створити проект, треба відкрити програму, з'явитися така заставка,

та відкриється сторінка створення проекту

Щоб створити новий проект, потрібно натиснути на "New Project ..."
У цьому випадку відкриється нове вікно, де можна вибрати мову програмування, назву проекту, його розташування, назву пакета з файлами проекту та можливість створення каталогу для подальшого використання в інших перехресних проектах. Щоб створити проект, де ми програмуватимемо в асемблері, потрібно вибрати - Assembler, після цього поміняємо назву проекту, його розташування, та вибираємо ОК.

З'явиться наступне вікно

Вибираємо "megaAVR, 8-bit"і знаходимо потрібний нам мікроконтролер, ми вибрали ATmega8.У правій частині заставки з'являється список пристроїв, які працюють із цим мікроконтролером, один з яких ми можемо підключити. Вибираємо ОК.

З'являється сторінка редактора тексту, яка дозволяє редагувати та налагоджувати програму. Поки сторінка чиста, вказано час і дату створення та назву файлу проекту, ім'я користувача. Існують додаткові вікна пристроїв введення-виводу, вікно звітів компіляції програми. тепер ми


можемо програмувати в асемблері.
Аналогічно створюється проект для програмування мовою СІ.