Вибір читачів
Популярні статті
Мікроконтролери (далі МК) міцно увійшли до нашого життя, на просторах інтернету можна зустріти дуже багато цікавих схем, які виконані на МК. Чого тільки не можна зібрати на МК: різні індикатори, вольтметри, прилади для дому (пристрої захисту, комутації, термометри…), металошукачі, різні іграшки, роботи тощо. можна перераховувати дуже довго. Першу схему на мікроконтролері я побачив років 5-6 тому у журналі радіо, і практично відразу ж перегорнув сторінку, подумавши про себе "все одно не зможу зібрати". Дійсно, в той час МК для мене були чимось дуже складним і незрозумілим пристроєм, я не уявляв, як вони працюють, як їх прошивати, і що робити з ними у разі неправильної прошивки. Але близько року тому, я вперше зібрав свою першу схему на МК, це була схема цифрового вольтметра на 7 сегментних індикаторах і мікроконтролері ATmega8. Так вийшло, що мікроконтролер я купив випадково, коли стояв у відділі радіодеталей, хлопець переді мною купував МК, і я теж вирішив купити, і спробувати зібрати щось. У своїх статтях я розповім вам про мікроконтролери AVR, навчу вас працювати з ними, розглянемо програми для прошивки, виготовимо простий та надійний програматор, розглянемо процес прошивки та найголовніше проблеми, які можуть виникнути і не тільки у новачків.
Основні параметри деяких мікроконтролерів сімейства AVR:
Мікроконтролер |
Пам'ять FLASH |
Пам'ять ОЗУ |
Пам'ять EEPROM |
Порти введення/виводу |
U харчування |
|
Додаткові параметри МК AVR mega:
Робоча температура: -55 ... +125 * С
Температура зберігання: -65 ... +150 * С
Напруга на виводі RESET щодо GND: max 13В
Максимальна напруга живлення: 6.0В
Максимальний струм лінії введення/виводу: 40мА
Максимальний струм по лінії живлення VCC та GND: 200мА
Розміщення висновків моделей ATmega 8X
Розміщення висновків моделей ATmega48x, 88x, 168x
Розміщення висновків у моделей ATmega8515x
Розміщення висновків у моделей ATmega8535x
Розміщення висновків у моделей ATmega16, 32x
Розміщення висновків у моделей ATtiny2313
Наприкінці статті прикріплено архів з датташитами на деякі мікроконтролери.
Настановні FUSE біти MK AVR
Запам'ятайте, запрограмований фьюз – це 0, не запрограмований – 1. Обережно варто ставитись до виставлення ф'юзів, помилково запрограмований ф'юз може заблокувати мікроконтролер. Якщо ви не впевнені, який саме фьюз потрібно запрограмувати, краще на перший раз прошийте МК без фьюзів.
Найпопулярнішими мікроконтролерами у радіоаматорів є ATmega8, потім йдуть ATmega48, 16, 32, ATtiny2313 та інші. Мікроконтролери продаються в TQFP корпусах та DIP, новачкам рекомендую купувати у DIP. Якщо купите TQFP, буде проблематичніше їх прошити, доведеться купити або паяти плату т.к. у них ніжки розташовуються дуже близько одна від одної. Раджу мікроконтролери в DIP корпусах, ставити на спеціальні панельки, це зручно і практично, не доведеться випоювати МК якщо закортить перепрошити, або використовувати його для іншої конструкції.
Багато сучасні МК мають можливість внутрисхемного програмування ISP, тобто. якщо ваш мікроконтролер запаяний на плату, то для того, щоб змінити прошивку нам не доведеться випоювати його з плати.
Для програмування використовується 6 висновків:
RESET- Вхід МК
VCC- Плюс харчування, 3-5В, залежить від МК
GND- Загальний провід, мінус харчування.
MOSI- Вхід МК (інформаційний сигнал у МК)
MISO- Вихід МК (інформаційний сигнал із МК)
SCK- Вхід МК (тактовий сигнал МК)
Іноді ще використовують виводи XTAL 1 і XTAL2, на ці висновки чіпляється кварц, якщо МК буде працювати від зовнішнього генератора, ATmega 64 і 128 виводу MOSI і MISO не застосовуються для ISP програмування, замість них виведення MOSI підключають до ніжки PE0, a MISO до PE1. При з'єднанні мікроконтролера з програматором, що з'єднують дроти повинні бути якомога коротшими, а кабель, що йде від програматора на порт LPT, так само не повинен бути занадто довгим.
У маркуванні мікроконтролера можуть бути незрозумілі літери з цифрами, наприклад Atmega 8L 16PU, 8 16AU, 8A PU та ін. Літера L означає, що МК працює від нижчої напруги, ніж МК без літери L, зазвичай це 2.7В. Цифри після дефісу або пробілу 16PU або 8AU говорять про внутрішню частоту генератора, який є в МК. Якщо фьюзи виставлені на роботу від зовнішнього кварцу, кварц повинен бути встановлений на частоту, що не перевищує максимальну за даташит, це 20МГц для ATmega48/88/168, і 16МГц для інших атмег.
#include
#include
#include
Доброго дня, шановні радіоаматори!
Вітаю вас на сайті
Що таке мікроконтролер і для чого він потрібен. Давайте звернемося до його визначення:
– мікросхема, призначена керувати електронними пристроями, чи інакше – простенький комп'ютер (мікро-ЕОМ), здатний виконувати нескладні завдання.
Тобто, по суті, мікроконтролер - це пристрій, що дозволяє втілити в життя наші ідеї (навіть марення), але, природно, в межах своїх можливостей. І найголовніше, втілення ідеї в життя досягається не створенням наворочених електронних конструкцій, а тільки, в основному, силою нашої думки (бажаєте стати чарівником?).
Найбільшою популярністю у радіоаматорів користуються два види мікроконтролерів:
– PIC- Фірми Microchip Technology
– AVR– фірми Atmel
Відразу хочу зробити невеликий відступ і пояснити свою позицію. Я не збираюся ні зараз, ні потім, міркувати про переваги того чи іншого виду мікроконтролерів, того чи іншого програмного забезпечення, і взагалі всього, що пов'язано з мікроконтролерами, щось радити, а тим більше нав'язувати читачам. Вся ця справа смаку, особистих уподобань та поставлених кінцевих цілей у вивченні мікроконтролерів. Ну а оскільки "неосяжне - не осягнути", все своє подальше оповідання я вестиму стосовно мікроконтролерів AVR і, не дуже поширеної, але мною улюбленої, програми "Algorithm Builder". У різних типів мікроконтролерів, програм є, звичайно, відмінності, але багато в них і загальне. А пізнавати світ мікроконтролерів ми будемо так, щоб потім отримані знання можна було б без проблем застосувати і до PIC, і до будь-якого програмного забезпечення. І ще раз нагадаю, ця серія статей – моя спроба допомогти тим, хто вперше почув про існування мікроконтролерів і бажає збагнути роботу з ними.
Що потрібно для того, щоб навчитися працювати з мікроконтролерами? Я виділив би кілька, на мій погляд, головних умов:
1. Бажання та наполегливість
.
Тут все дуже просто: є бажання – все вийде. А бажання із наполегливістю – взагалі, річ суперська.
2. Знання пристрою мікроконтролера.
Тут не важливі глибокі знання (та може і взагалі не потрібні), але знати, що є на борту мікроконтролера необхідно. Тільки знаючи, з чого складається мікроконтролер, які пристрої в ньому є, їх можливості, як вони працюють – тільки тоді ми зможемо використовувати можливості мікроконтролера на повну котушку.
3. Знання мови програмування та команд управління мікроконтролером.
Як працюватиме мікроконтролер, які завдання ви на нього покладаєте і як він їх виконуватиме, визначається закладеною в нього програмою – програмою яку для мікроконтролера складаєте ви самі. І на цьому пункті ми зупинимося докладніше, щоб розглянути питання, які можуть виникнути в майбутньому.
Програма(У перекладі це слово означає – “припис”) – попередній опис майбутніх подій чи дій.
Наприклад, ми хочемо, щоб мікроконтролер блимав світлодіодом. Просте завдання, але для того, щоб мікроконтролер виконав це завдання, ми попередньо повинні, крок за кроком, описати всі дії мікроконтролера, написати програму, яку він повинен виконати для отримання потрібного нам результату - миготливий світлодіод. Щось на кшталт такого:
♦ Запалити світлодіод:
- налаштувати висновок, до якого підключений світлодіод для роботи на виведення інформації
- подати цей висновок логічний рівень, який дозволить запалити світлодіод
♦ Зачекати деякий час:
- перейти до підпрограми, що формує паузу (яку теж потрібно “розжувати”)
- по виконанню підпрограми паузи повернутися до основної програми
♦ Погасити світлодіод:
- подати на висновок логічний рівень, що гасить світлодіод
і таке інше.
З терміном Програманерозривно пов'язаний інший термін - Алгоритм(як Вовк та Заєць, Том та Джеррі).
Алгоритм- Набір інструкцій, що описують порядок дії для досягнення потрібного результату.
Якщо у програмі ми докладніше прописуємо діїмікроконтролера, то в алгоритмі ми визначаємо порядок діймікроконтролера, на основі яких ми потім створимо програму. За аналогією з наведеним вище прикладом:
♦ Засвітити світлодіод
♦ Зачекати деякий час
♦ Погасити світлодіод
і таке інше.
Таким чином, алгоритм – це попередник програми. І чим ретельно і продумано буде створено алгоритм, тим простіше створюватиме програму.
Отже, програма для мікроконтролера – це послідовність дій мікроконтролера у вигляді набору команд та інструкцій, які він має виконати для досягнення поставлених нами цілей.
Команди для мікроконтролера мають вигляд набору одиниць та нулів:
00110101 011000100
так звані - коди команд,а коди команд – це мова, яка розуміє мікроконтролер. А для того, щоб перекласти наш алгоритм з російської мови на мову мікроконтролера – у ці набори нулів і одиниць, існують спеціальні програми.
Ці програми дозволяють описати порядок роботи для мікроконтролера більш-менш зрозумілою для нас мовою, а потім перекласти цей порядок на мову зрозумілу мікроконтролеру, в результаті чого виходить так званий машинний код- Послідовність команд та інструкцій (ті самі нулі та одиниці) які тільки і розуміє мікроконтролер. Текст програми, написаний програмістом, називається вихідним кодом. Переклад програми з мови програмування (вихідного коду) на мову мікроконтролера (машинний код) здійснюється трансляторами. Транслятор перетворює текст програми на машинні коди, які потім записуються на згадку про мікроконтролера.
У таких програмах порядок роботи мікроконтролера описується спеціальною мовою – мовою програмування. Мова програмування відрізняється від нашої, людської мови. Якщо наша мова спілкування служить в основному для того, щоб обмінюватися інформацією, то:
Мова програмування – це спосіб передачі команд, інструкцій, чіткого керівництва до дії мікроконтролера.
Існує безліч мов програмування і їх можна поділити на два типи:
– мови програмування низького рівня
– мови програмування високого рівня
Чим вони відрізняються. А відрізняються вони своєю близькістю до мікроконтролера.
На зорі зародження мікропроцесорної техніки програми писали в машинних кодах, тобто весь алгоритм роботи послідовно прописували у вигляді нулів і одиниць. Ось так, наприклад, виглядала програма:
01000110
10010011
01010010
Навряд чи хтось зможе розібратися в такому наборі комбінацій із двох цифр, а праця перших програмістів була дуже трудомісткою. Для полегшення свого життя програмісти і стали створювати перші мови програмування. Так ось, чим ближче мова програмування до такого набору нулів і одиниць тим більше він "низького рівня", а чим далі від них - тим більше "високого рівня".
Найпоширеніші мови програмування для мікроконтролерів:
- мова низького рівня - Асемблер
– мова високого рівня – С (Сі)
Давайте подивимося на прикладі їхньої відмінності (ці приклади абстрактні).
Допустимо нам треба скласти два числа: 25 та 35.
У машинних кодах ця команда може мати такий вигляд:
00000101 1101001
Мовою низького рівня:
ADD Rd, Rr
Мовою високого рівня:
25+35
Різниця мов низького та високого рівня видно неозброєним оком, коментарі, як кажуть, зайві.
Але давайте копнемося в цих прикладах глибше. Приклад машинного коду не будемо розбирати, оскільки він ідентичний прикладу на Асемблері. За своєю суттю, асемблерні команди це ті ж машинні коди (команди) яким просто, щоб не заблукати в нулях і одиницях, присвоєні буквені абревіатури. Асемблерною командою ADD Rd, Rr ми ставимо мікроконтролеру завдання скласти два числа, які знаходяться (а для цього ми повинні їх записати туди попередньо) – перше в Rd, друге в Rr, а результат додавання помістити в Rd. Як бачите, ми ставимо дуже конкретне завдання мікроконтролеру: де взяти, що з цим зробити і куди помістити результат. І тут ми працюємо безпосередньо з микроконтроллером.
Команда мовою високого рівня: 25+35, звична для нас математична запис, що тішить наше око. Але в цьому випадку ми не працюємо безпосередньо з мікроконтролером, ми просто ставимо йому завдання скласти два числа. Результат і послідовність дій в даному випадку буде той же, що і при виконанні асемблерної команди: спочатку ці два числа будуть кудись записані, потім складені а результат кудись поміщений.
І ось тут криється головна відмінність мов високого та низького рівня. Якщо в Асемблері ми контролюємо весь процес (хочемо ми того, чи ні): ми знаємо де записані ці два числа, і ми знаємо де буде результат, то в мові високого рівня ми процес не контролюємо. Програма сама вирішує куди заздалегідь записати числа і куди помістити результат. Найчастіше нам це і не треба знати, адже для нас головне підсумок – число 60 на виході. Як результат, програми на мовах високого рівня більш читані, приємні для ока і менше за розміром - адже нам не доводиться "лізти в усі дірки" і розписувати кожен крок мікроконтролера, програма це робить потім за нас, коли компілює її - перекладає в машинні коди . Але тут є мінус. Два однакових алгоритму написаних на Ассемблері та на Сі, після перетворення їх у машинні коди матимуть різний розмір: програма написана на Ассемблері буде на 20-40% коротше програми написаної на Сі – чорт його знає, яким шляхом йде Сі для досягнення потрібного нам результату . І трапляються випадки, коли немає довіри до мови високого рівня і в програмі на Сі роблять вставки коду, написані на Асемблері.
Професійні програмісти, як правило, знають кілька мов програмування (або працюють у команді, в якій є фахівці з різних мов), творчо поєднуючи їхні можливості та переваги в одній програмі. Ну а нам, любителям, треба знати хоча б одну мову (для початку), і починати треба (а я в цьому твердо впевнений, і ніхто мене не переконає) з язика низького рівня – Асемблера.
Ну що, я думаю, і тут нам все зрозуміло, – мову програмування вивчати треба, інакше – ніяк.
Команди та інструкції для керування мікроконтролером.
У мікроконтролерів AVR більше 130 різних команд, які дозволяють йому реалізувати всі закладені у ньому можливості. Але одразу скажу – мало хто з аматорів знає їх усе і тим більше користується всіма. Зазвичай, у аматорській практиці вистачає знання та половини команд, а то й менше. Але вивчати команди треба. Чим більше команд ви будете знати, тим витонченіші (у хорошому сенсі слова) та елегантніші програми будуть виходити.
Арифметико-логічний пристрій та організація пам'яті – пам'ять програм, пам'ять даних, енергонезалежна пам'ять
♦
♦
♦
Я не раз і не два говорив, що вивчення МК треба починати з асемблера. Цьому було присвячено цілий курс на сайті (правда він не дуже послідовний, але поступово я його зачісую до адекватного вигляду). Так, це складно, результат буде не в перший день, зате ти навчишся розуміти що відбувається у тебе в контролері. Знатимеш як це працює, а не по мавпій копіювати чужі вихідники і намагатися зрозуміти чому воно раптом перестало працювати. Крім того, Сі набагато простіше наробити бидлокода, який вилізе вилами в невідповідний момент.
На жаль, всі хочуть результат негайно. Тому я вирішив піти з іншого боку — зробити взутку Сі, але з показом його нижньої білизни. Хороший програміст-ембеддер завжди міцно тримає свою залізницю за шкварник, не даючи їй ні кроку ступити без дозволу. Так що буде спочатку Сі код, потім те, що народив компілятор і як все це працює насправді:)
З іншого боку, у Сі сильна сторона це переносимість коду. Якщо, звісно, писати все правильно. Поділяючи алгоритми роботи та їх залізні реалізації у різні частини проекту. Тоді для перенесення алгоритму в інший МК достатньо буде переписати лише інтерфейсний шар, де прописано все звернення до заліза, а весь робочий код залишити як є. І, звичайно ж, читальність. Сишний вихідник простіше зрозуміти з першого погляду (хоча ... мені, наприклад, вже пофігу на що фтикати - хоч си, хоч асм:)), але, знову ж таки, якщо правильно все написати. Цим моментам я теж приділятиму увагу.
Як піддослідна залозка на якій буде ставитися левова частка всіх прикладів буде моя налагоджувальна плата.
Перша програма на Сі для 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 там уже прописана по дефолту).
Головна функція.
Програма мовою Сі вся складається з функцій. Вони можуть бути вкладеними і викликатись один з одного в будь-якому порядку та різними способами. Кожна функція має три обов'язкові параметри:
Усі значення передані і повертаються мають бути якогось типу, залежно від даних.
Будь-яка програма на Сі повинна містити функцію 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);< Страшна? Насправді реалного коду тут лише п'ять останніх рядків. Все що #defineце макромова препроцесора. Майже те ж бадилля, що і в Асемблері, але синтаксис дещо інший. Вони полегшать твої рутинні операції з обчислення потрібних коефіцієнтів. У першому рядку ми говоримо, що замість XTALможна сміливо підставляти 8000000, а L- Вказівка типу, мовляв long - це тактова частота процесора. Те ж саме baudrate- Частота передачі даних по UART. bauddividerвже складніше, замість нього буде підставлятись вираз обчислений за формулою з двох попередніх. Так що все, що зроблено як #defineможна сміливо викинути, а потрібні числа підрахувати на калькуляторі і відразу ж вписати в рядки UBBRL = …. та UBBRH = ….. Можна. Але! Робити цього КАТЕГОРИЧНО НЕ МОЖНА! Працюватиме і так і так, але в тебе в програмі з'являться так звані магічні числа— значення взяті незрозуміло звідки й незрозуміло навіщо і якщо ти через пару років відкриєш такий проект, то зрозуміти що це за значення буде дуже важко. Та й зараз, захочеш ти змінити швидкість, або зміниш частоту кварцу і все доведеться перераховувати заново, а так змінив пару циферок у коді і все саме. Загалом, якщо не хочеш уславитися бидлодером, то роби код таким, щоб він легко читався, був зрозумілий і легко модифікувався. Далі все просто: Запис виду 1< Готово, настав час подивитися що вийшло. Тисніть на компіляцію та запуск емуляції (Ctrl+F7). Налагодження Справа в тому, що спочатку, насправді, вона стояла на рядку UBRRL = LO (bauddivider); Адже те, що у нас в define це не код, а просто попередні обчислення, ось симулятор трохи і затупив. Але тепер він усвідомив, першу інструкцію виконано і якщо ти залізеш у дерево I/O View, в розділ USART і подивишся там на байт UBBRL то побачиш, що там значення вже є! 0х33. Зроби ще один крок. Подивись як зміниться вміст іншого регістру. Так пройди їх усі, зверни увагу на те, що всі зазначені біти виставляються як я тобі і говорив, причому виставляються одночасно для всього байта. Далі Return справа не піде – програма скінчилася. Розтин Спочатку буде бадилля із серії: 00000000: 940C002A JMP 0x0000002A Jump +00000002: 940C0034 JMP 0x00000034 Jump +00000004: 940C0034 JMP 0x00000034 Jump +00000006: 940C0034 JMP 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C0034 JMP 0x00000034 Jump +0000000E : 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00 034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP00 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +0000 4 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP 0x0 Це таблиця векторів переривань. До неї ми ще повернемося, поки просто подивися і запам'ятай, що вона є. Перша колонка - адреса осередку флешу в якій лежить команда, друга код команди третя мнемоніка команди, та сама асемблерна інструкція, третя операнди команди. Та й автоматичний комент. 0000002B: BE1F OUT 0x3F,R1 Перейти до I/O location Запис цього нуля на адресу 0x3F, Якщо ти подивишся в колонку I/O view, то побачиш що адресу 0x3F це адреса регістра SREG — прапорового регістру контролера. Тобто. ми обнулюємо SREG, щоб запустити програму на нульових умовах. 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 Стрибок у сааааамий кінець програми, а там у нас заборона переривань і зациклювання наглухо саме на себе: 00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relative jump Це випадок непередбачених обставин, наприклад виходу з функції main. З такого зациклювання контролер можна вивести або апаратним скиданням, або, ймовірно, скиданням від сторожового собаки - watchdog. Ну або, як я говорив вище, підправити це місць у хекс редакторі і поїхати куди нам душі завгодно. Також зверніть увагу на те, що буває два типи переходів JMP і RJMP перший це прямий перехід за адресою. Він займає чотири байти і може зробити прямий перехід по всій області пам'яті. Другий тип переходу – RJMP – відносний. Його команда займає два байти, але перехід він робить від поточного положення (адреси) на 1024 кроки вперед або назад. І його параметрах вказується зміщення від поточної точки. Використовується найчастіше, т.к. займає вдвічі менше місця у флеші, а довгі переходи потрібні рідко. 00000034: 940C0000 JMP 0x00000000 Jump А це стрибок на початок коду. Перезавантаження свого роду. Можеш перевірити, чи всі вектори стрибають сюди. З цього висновок — якщо ти зараз дозволиш переривання (вони дефолтом заборонені) і в тебе переривання пройде, а обробника немає, то буде програмне скидання — програму кине на початок. Функція main. Все аналогічно навіть можна і не описувати. Подивися щойно до регістру заноситься вже обчислене число. Препроцесор компілятора рулить! Тож жодних «магічних» чисел! 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< А ось тут косяк: 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: Якщо ви читаєте цю статтю, можливо у вас виникло бажання зрозуміти, як працюють мікроконтролери, і швидше за все постали питання: Спробуємо відповісти на ці запитання. У промисловості, дещо інакше, перше місце з великим відривом посідає Renesas Electronicsна другому Freescale, на третьому Samsungпотім йдуть Microchipі TI, Далі всі інші. Ми вивчатимемо 8-бітні мікроконтролери AVR, сімейства ATMEGA 8 та 16 серії. Вибір визначився, знову ж таки доступністю, наявністю безлічі аматорських розробок, величезною кількістю навчального матеріалу. Наявністю різноманітних вбудованих компонентів та функціональністю цього сімейства. Найбільш поширені з них AVRStudio, ATmelStudio, WINAVR, CodeVision, IAR Embedded Workbench. ATmelStudio дозволяє створювати проекти і писати програми як в асемблері, так і на СІ. Спочатку завжди постає питання: яку мову програмування вибрати, щоб писати ефективні програми? Відповім просто: потрібно вміти писати як мінімум двома мовами асемблері та СІ. Асемблер просто необхідний, коли потрібно написати швидкі та компактні підпрограми та макроси, різні драйвери пристроїв. Але, коли потрібно створити об'ємний проект, побудований на складних алгоритмах, без знання СІ може бути витрачено дуже багато часу, особливо в процесі налагодження, а якщо виникне бажання перенести на іншу платформу, наприклад PIC18 або STM, може стати нерозв'язною проблемою. Щоб наочно бачити результат своєї роботи, не використовуючи паяльник чи макетну плату достатньо встановити програму Proteus. Енергонезалежна пам'ять програм та даних Вбудована периферія Спеціальні мікроконтролерні функції Висновки I/O та корпусу Робоча напруга Робоча частота відмінності ATMEGA16 від 8 Інтерфейс JTAG (сумісний із IEEE 1149.1) Чотири канали PWM / ШИМ 8-канальний 10-розрядний аналого-цифровий перетворювач Шість режимів зниженого споживання: Idle, Power-save, Power-down, Standby, Extended Standby та зниження шумів ADC 32 програмовані лінії введення/виводу 40-вивідний корпус PDIP та 44-вивідний корпус TQFP Щоб створити проект, треба відкрити програму, з'явитися така заставка, та відкриється сторінка створення проекту Щоб створити новий проект, потрібно натиснути на "New Project ..." З'явиться наступне вікно Вибираємо "megaAVR, 8-bit"і знаходимо потрібний нам мікроконтролер, ми вибрали ATmega8.У правій частині заставки з'являється список пристроїв, які працюють із цим мікроконтролером, один з яких ми можемо підключити. Вибираємо ОК. З'являється сторінка редактора тексту, яка дозволяє редагувати та налагоджувати програму. Поки сторінка чиста, вказано час і дату створення та назву файлу проекту, ім'я користувача. Існують додаткові вікна пристроїв введення-виводу, вікно звітів компіляції програми. Тепер ми
Ну, а LOі HIцього результату візьмуть молодший і старший байти, т.к. в один байт воно може не влізти. У HIробиться зсув ікса (вхідний параметр макросу) вісім разів направо, в результаті від нього залишиться лише старший байт. А в LOми робимо побітове І з числом 00FF, в результаті залишиться лише молодший байт.
Всі ці "UBRRL і C" це регістри конфігурації UART передавача за допомогою якого ми будемо спілкуватися зі світом. І зараз ми надали їм потрібні значення, налаштувавши на потрібну швидкість і потрібний режим.
Пробігли всілякі прогреси, студія змінилася і біля входу в функцію main з'явилася жовта стрілочка. Це де процесор в даний момент, а симуляція на паузі.
Тепер скинь симуляцію у нуль. Натисніть там 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 JMP 0x0000002A Jump +00000002: 940C0034 JMP 0x00000034 Jump 00000004: 940C0034 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C00 0000000E: 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP 0x00000034 Jump +0000001C : 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00 034 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP00
Так от, якщо ти подивишся, то тут суцільні переходи. А код команди JMP чотирьох байтний, у ньому міститься адреса переходу, записана задом наперед - молодший байт за молодшою адресою та код команди переходу 940C 1
2
3
4
+0000002C: E5CF LDI R28,0x5F Load immediate +0000002D: E0D4 LDI R29,0x04 Load immediate +0000002E: BFDE OUT 0x3E,R29 I/O location +00000002
1
2
+00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Relative jump
1
+00000034: 940C0000 JMP 0x00000000 Jump
1
2
3
4
5
6
7
8
9
10
11
12
< 1
2
3
+0000003E: E080 LDI R24,0x00 Load immediate +0000003F: E090 LDI R25,0x00 Load immediate +00000040: 9508 RET Subroutine return
Alexei78зварганив плагінчик для файрфокса, що полегшує навігацію по моєму сайту та форуму.
Обговорення та скачування,
Сучасне радіоаматорство неможливо уявити без мікроконтролерів, і це очевидно. В останні десятиліття мікроконтролери різних виробників стали поширені у різних сферах діяльності. Нерідко їх можна зустріти в найнесподіваніших пристроях та конструкціях. Ми з вами є свідками комп'ютеризації та автоматизації навколишніх процесів. Істина така, що без знання основ програмування створювати сучасні конкурентоспроможні пристрої стало практично неможливо.
4. Яку літературу вивчати?
1. Який мікроконтролер вибрати для роботи?
Великою популярністю у радіоаматорів користуються 8-бітові мікроконтролери PICфірми Microchip Technology та AVRфірми Atmel, 16-бітові MSP430фірми TI, а також 32-бітові мікроконтролери, архітектури ARM.
Популярність визначається ціною та доступністю, чималу роль відіграють наявність технічної інформації та вартість програмного супроводу.2. Яке середовище розробки використовуватиме програмування обраного мікроконтролера?
Для AVR створено різні інтегровані середовища розробки (IDE, Integrated development environment).
IDE– це система програмних засобів, що використовується програмістами для розробки програмного забезпечення (ПЗ), до складу якої входять:
текстовий редактор,
компілятор та/або інтерпретатор,
засоби автоматизації складання,
відладчик.
Для того, щоб писати програми, ми скористаємося безкоштовною IDE ATmelStudio версії 6та вище.
Завантажити Atmel Studio можна з офіційного сайту після реєстрації (реєстрація абсолютно безкоштовна і нічого не зобов'язує!)
Окрім цього, зараз з'явилися апаратні обчислювальні платформи Arduino, робота з якими вимагає знання мови СІ++
Тому писатимемо програми як в асемблері, так і на СІ.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
23 програмовані лінії введення/виводу
28-вивідний корпус PDIP, 32-вивідний корпус TQFP та 32-вивідний корпус MLF
2,7 - 5,5 В (ATmega8L)
4,5 - 5,5 (ATmega8)
0 - 8 МГц (ATmega8L)
0 - 16 МГц (ATmega8)
16 Кбайт внутрішньосистемно програмованої Flash пам'яті (In-System Self-Programmable Flash)
Можливість сканування периферії, що відповідає стандарту JTAG
Розширена підтримка вбудованого налагодження
Програмування через JTAG інтерфейс: Flash, EEPROM пам'яті, перемичок та біт блокування
8 несиметричних каналів
7 диференціальних каналів (тільки у корпусі TQFP)
2 диференціальних канали з програмованим посиленням 1, 10 або 200 крат (тільки в корпусі TQFP)AtmelStudio
Якщо Ви тільки починаєте, то потрібно завантажити та встановити програму AtmelStudio з офіційної сторінки atmel.com
Після встановлення програми AtmelStudio можна розпочати створення проекту.
Проект– це ваша програма, яку ви писатимете, налагоджуватимете і прошиватимете, після компіляції, на згадку про мікроконтролера.
У цьому випадку відкриється нове вікно, де можна вибрати мову програмування, назву проекту, його місцезнаходження, назву пакета з файлами проекту та можливість створення каталогу для подальшого використання в інших перехресних проектах. Щоб створити проект, де ми програмуватимемо в асемблері, потрібно вибрати - Assembler, після цього змінимо назву проекту, його розташування, і вибираємо ОК.
можемо програмувати в асемблері.
Аналогічно створюється проект для програмування мовою СІ.
Статті на тему: | |
Стагнація: що це таке, причини формування та шляхи подолання проблеми Причини стагнації
Термін «стагнація» майже завжди вживається в негативному контексті. Історичний факультет Спбгу скасовується
Історичний факультет СПбДУ Історичний факультет... Розселення аварійного житла
Багато людей змушені проживати в умовах, які вважаються... |