середа, 22 травня 2013 р.

Експеримент 01. Порти вводу/виводу, робочі регістри загального призначення.


     Отже починаємо практичні експерименети з МК. В цій статті розглянемо основи, без яких не обходиться ні один проект на МК. Це використання портів вводу/виводу і робочих регістрів загального призначення. І справді - який зміст в МК, який не зв'язується з "оточуючим середовищем" (а це відбувається через порти В/В). А без використання робочих регістрів загального призначення (РРЗП) практично неможлива ні одна програма для МК.


    Підготовка макетної плати

     Спершу підготуємо апаратну частину. На нашій макетній платі до порту А під'єднаємо 8 світлодіодів, згідно схеми:
Тут EXLED1...EXLED8 - наші світлодіоди. Ось як раз тут і згодилося б виконати розєми порта з кроком у 5мм, щоб просто вставити круглі світлодіоди, ну я під'єднав через роз'єм зі шлейфом, ось так:
До порта В у нас приєднані кнопки на макетці.

     З апаратною частино закінчили. 

Тепер трохи теорії.

     Що ж являє собою порт вводу/виводу МК. У мікроконтролерів AVR порти 8-розрядні, тобто кожен порт має 8 виводів-ножок МК, що позначаються в даташті буквами Рху, де х- назва порта (порти називають латинськими буквами A,B,C,D і так далі), а y - номер біта порта від 0 до 7. Тобто на малюнку:
РА0...7 і РВ0...7 це виводи портів А і В. Також часто зустрічаються "неповні" порти, тобто припустимо є виводи РD0...3. Якщо дивитися на картинку (а це є схема розміщення виводів нашого МК ATTiny 26), то бачимо, що біля кожного вивода порта в дужках ще є купа абревіатур. Це так звані альтернативні функції виводів, тобто виводи портів можна сконфігурувати не лише як цифрові лінії вводу/виводу, а і по іншому, наприклад як аналоговий вхід АЦП (ADC) та ін. Проте це ми розглянемо у інших статтях.

     Чому кожен порт має саме 8 розрядів. Тут справа в тому, що АВР це 8 розрядний мікроконтролер, тобто усі операції він виконує над 8-розрядними двійковими числами. Отже усі його регістри також є 8 розрядними. А керування портами здійснюється як раз за допомогою регістрів, тому дуже зручно було зробити їх також 8 розрядними.

    Як же відбувається керування портом. При використанні вивода як цифрового порта вводу/виводу, він може виконувати функції:
   1. Цифрового входу (вільний вивід в такому режимі буде давати невизначений сигнал)
   2. Цифрового входу з підтягуючим резистором на + живлення (в такому випадку вільний вхід буде давати лог.0)
   3. Виходу (двохтактний вихід, лог 1 - на виході +живлення, лог.0 - вихід з'єднаний з "землею". Допустимий струм в любому стані складає біля 20ма, що дозволяє без проблем під'єднувати наприклад світлодіоди).

    Для керування портами використовуються керуючі регістри DDRx і PORTx, де х-назва порта. Також є регістр PINx, в якому знаходяться логічні стани вивода порта (з цього регістра можна тільки зчитувати дані, запис в нього нічого не дає ).
     Отже регістр DDRx (DDRA і DDRB для ATTiny 26 ) задає "напрям" роботи порта. Якщо у певному біті цього регістра записаний 0 то відповідний вивід порта буде працювати як вхід, а якщо 1 - то як вихід.
     Тобто, припустимо, маємо такі значення:

В такому випадку у нас виводи РА0, РА3, РА4, РА6 будуть працювати як виходи, РА1, РА2, РА5, РА7 - як входи.
Аналогічно для порта В. Для нашого використання ATTiny 26 порт  В є неповним, його вивід РВ7 зайнятий альтернативною функцією RESET і не може бути використаний як вхід/вихід.

     Регістр PORTx має подвійне призначення. Якщо вивід порта встановлений на вихід , то значення відповідного біта регістра PORTx буде виводитись на вивід. Якщо ж вивід сконфігурований як вхід, то 1 в відповідному біті PORTx вмикає підтягуючий резистор до +живлення, 0 - вимикає.

    З регістра PINx ми в любий момент можемо зчитати стан виводів нашого порта. Тобто наявність лог.1 на виводі записує 1 у відповідний біт регістра PINx, а лог.0 - відповідно 0. Чи порт є входом чи виходом, значення не має.

Загальна таблиця конфігурації порта (взята з книжки Евстифеева)


    Тепер перейдемо до робочих регістрів загального призначення (РРЗП).
РРЗП - це ячейки пам'яті, до яких "ядро" МК має прямий доступ і може виконувати операції над значеннями, що записані в цих ячейках. Якщо розглянути архітектуру МК ATTiny 26:
то бачимо, що РРЗП (Регистры общего назначения рос.) напряму звязані з АЛП (арифметико-логічний пристрій, тобто "ядро")
     Усі операції з рештою пристроїв, що входять у склад МК, виконуються тільки з використанням  РРЗП. Так, наприклад, щоб зберегти якесь число в ячейку ОЗП треба спочатку помістити його в РРЗП. Так само практично всі операції виводу в порти та інші регістри відбуваються через РРЗП (виключення є, але їх небагато).

    У мікроконтролерах AVR є 32 РРЗП, що знаходяться у пам'яті даних МК за адресами $00...$1F (адреси прийнято записувати у 16-ковій системі). Далі ідуть службові регістри керування (серед них ті ж PORTx PINx DDRx), ще далі - ячейки ОЗП. (У AVR пам'ять даних і пам'ять програм розділені і мають окрему адресацію, так звана Гарвардська архітектура )
РРЗП мають позначення R0...R31, притому "повноцінними" є R16...R31, регістри R0...R15 не можуть працювати з деякими командами, наприклад з ними не можуть виконуватися операції з константою.
Також регістри R26,R27   R28,R29  R30,R31 утворюють так звані регістрові пари X,Y,Z , що використовуються для роботи з адресацією даних.

     Переходимо до практики

Створення проекту

Для початку створимо папку для наших проектів. Я, наприклад створюю С:\AVRPRJ
Запускаємо ATMEL STUDIO 6.1. Може з'явитися вікно з повідомленням про наявність оновлення (UPDATE), клацаємо кнопочку UPDATE, при потребі вводимо дані нашого  ATMEL акаунту (емейл і пароль).
У вікні що з'явилося клацаємо New project на лівій панелі

У вікні вибираємо на лівій панелі - Assembler, посередины з'яаиться AVR Assembler Project

Знизу напроти поля Location натискаємо кнопочку Browse і вказуємо нашу папку. В полі Name пишемо назву нашого проекту - EXP1.
Натискаємо ОК.

З'являється вікно вибору МК - вибираємо зі списку наш ATTiny26
Натискаємо ОК
Відкривається середовище розробки

Написання першої програми

Основне найбільше вікно - це вікно в якому набиратимемо код проекту (EXP1.asm)
Тут ми і почнемо вчитися програмувати на Асемблері.

Зеленим там відмічаються коментарі. Коментарі можна писати або, починаючи з ;(однорядковий), або, якщо коментар має декілька рядків - він повинен починатися з /* і закінчуватися */.
В "шапці" коментарів можна написати автора, під який МК написана програма та інші загальні дані.

Далі почнемо наш код.

 Скачати АСМ файл можна ТУТ

УВАГА!!! СКАЧАНІ АСМ ФАЙЛИ НЕ ВАРТО ВІДКРИВАТИ НАПРЯМУ ЗА ДОПОМОГОЮ АТМЕЛ СТУДІО! ТРЕБА ВІДКРИТИ ФАЙЛ "БЛОКНОТОМ" (NOTEPAD), СКОПІЮВАТИ ТЕКСТ ПРОГРАМИ І ВСТАВИТИ ЙОГО У ВІКНО ВАШОГО ПРОЕКТУ!!!

 Отже ми написали першу програму на асемблері 
Розглянемо її.

Після "шапки" коментарів, починається безпосередньо сама програма. рядок 
Reset:
це мітка. Мітка може мату любу назву, і закінчується значком :
Мітки застосовуються для здійснення переходів (при компіляції в машинний код мітка замінюється на адресу в пам'яті програм)
Тут починається виконання програми після скидання (reset), тому я дав таку назву мітці.

     Наступний рядок це команда асемблера ldi r16,0b11111111


Команда LDI [РРЗП],[Константа] здійснює завантаження значення константи в регістр РРЗП. Працює тільки з РРЗП R16...R31.


Константи (числові значення) в асемблері можна записувати у десятковій системі (просто 5, 240, 32), в двійковій (з префіксом 0b перед числом - 0b11101010,  0b1011), чи в шіснадцятковій (з префіксом 0x перед числом 0xF1, 0xAC).

     Далі іде  out DDRA, r16; 

Команда OUT [СЛУЖБОВИЙ РЕГІСТР],[РРЗП] виводить значення, що міститься в РРЗП у службовий регістр Працює з усіма  РРЗП.

Як бачимо, напряму вивести константу (число) в керуючий регістр порта неможливо (тобто команда ldi DDRA,0b11111111) дасть помилку при компіляції. Для виводу числа в керуючий регістр треба спочатку помістити це число в РРЗП.

     Далі ми завантажуємо в r16 потрібні значення і виводимо їх у керуючі регістри портів, здійснюючи їх конфігурацію. Таким чином, у нас порт А буде настроєний на вихід, порт Б - на вхід, притому на виводах РВ0...РВ4 будуть включені підтягуючі резистори на +живлення (до цих виводів підключені кнопки).

     Мітка Main: це так званий початок основного циклу програми. Взагалі, люба програма для МК містить основний цикл, де виконуються дії, що пов'язані з конкретним використанням МК. Якщо циклу не буде, програма буде виконуватись лінійно і вийшовши за межі програмної пам'яті викличе збій МК.

     Далі ми якраз і виконуємо наші дії - тобто послідовністю команд  LDI - OUT виводимо в порт А одиничку в 0-ий розряд, вмикаючи сперший світлодіод в лінійці.

    Останньою командою є rjmp Main

Команда RJMP [ім'я мітки] виконує безпосередній перехід до вказаної мітки.

    Отже виконання програми переходить до мітки Main: і зациклюється.

Компіляція


     Ми маємо набраний код, тепер потрібно виконати компіляцію. Для цього ідемо в верхнє меню Build - Build Solution (або просто натискаємо F7). 


Після цього у нижньому вікні (Output) повинне з'явитися щось таке:
Якщо у набраному коді є помилки, то вискакує повідомлення про помилку. Наприклад, змінимо будь яку команду ldi на lde  (такої команди не існує) і натиснемо F7.
Знизу замість Output з'явиться Error List - де буде описано яка помилка і в якому рядку виникла. При подвійному клацанні на помилці, курсор у вікні коду стане на потрібний рядок (здається це не працює у старіших версіях студії).
Виправимо усе як було і знову натиснемо F7.

Тепер подивимось на праву панель. Знайдемо вкладку Solution Explorer (серед VA View, ASF та ін) і клаценмо по ній. Тепер у віконечку двічі клацнемо на Dependencies і побачимо що там є файл tn26def.inc
     У 5 і 6 версіях студії приєднання цього файла до проекта здійснюється автоматично, при виборі типу МК, Це файл - у якому знаходяться асоціації реальних адрес усіх регістрів та іншого до їх буквенних позначень! Без цього файлу програма не знала б, що таке R16, DDRA, та ін, бо сам контролер оперує тільки з адресами регістрів а не з їх назвами.  Можна клацнути двічі по файлу і він відкриється у вікні коду як вкладка.
   
     Ну зараз розбиратися з тим не будемо, просто показав що таке є.

Симуляція виконання програми на ПК


     Спробуємо просимулювати виконання програми, поки що не завантажуючи її у наш контролер.
Ідемо у верхнє меню - Debug - Start Debugging and break. У віконечку, що відкрилося вибираємо Simulator (а більше там нічого і нема :-)) і натискаємо ОК

У нас в вікні кода появиться жовта стрілочка напроти першого рядка після мітки Reset, а справа з'явиться вікно Processor. 
Цей жовтий рядок показує місце, де зараз знаходиться виконання програми, вікно  Processor. відображає стан МК, наприклад значення Регістрів.

Зразу змінимо значення Frequency на 8 МГц, усі наші подальші експерименти будуть відбуватися саме при цій частоті МК.

Ідемо в меню Debug - Windows - IO View .тепер у нас з'явилося вікно IO View
Тут можна дивитися стан портів та інше. Виберемо ПОРТА. Тепер повернемося на вкладку Processor. 
І натиснемо F11 (виконує крок програми). Як бачимо - у нас
Cycle counter стало рівним 1 (тобто програма зробила 1 крок), регістр R16 змінив значення на    0xFF (0b11111111). Рядочок Stop Watch показує, скільки часу зайняло виконання програми.

     Тепер відкриємо IO View, і виконаємо наступний крок  F11
Бачимо, що підсвічений рядок у коді змістився нижче, а в регістр DDRA записалися 1 у всі біти.

Продовжимо натискати  F11, дивлячись, які значення записуються у біти портів. Коли дойдемо до останнього рядка - побачимо зациклення - виконання перейдо до мітки Main і продовжиться.

Ось результат виконання програми - на 0 виводі порта А буде лог.1, та сама 1 з'явится у нульовому біті регістра PINA.

Йдемо в меню Debug - StopDebugging. Симуляція завершена.

Прошиваємо МК

     Запускаємо Khazama AVR Programmer.
Тепер підключимо шлейф програматора до макетки, а програматор ввімкнемо в ЮСБ гніздо.
Прослідкуємо, щоб у рядочку AVR показувався наш ATTINY26.
Тепер зробимо одну річ - запрограмуємо фьюзи, щоб змінити тактову частоту МК. Більше ми не будемо цього робити найближчим часом.

Отже ідемо в меню Khazama   Command - Fuses and lock bits


Натискаємо кнопочку Read ALL, ніяку іншу!!!
Отримуємо заводські значення, прошиті в МК:

Lock bits - це сама жостка штука - змінивши її можна заблокувати МК для подальшого програмування.

Н-Fuse пункт Serial Program downloading теж не чіпати - можна заблокувати внутрісхемне програмування МК.   Brown-out detector це штука, яка потрібна для надійного старту МК, нехай лишається як є.

А от у L-Fuse міняємо значення на Int RC OSC 8MHz Start Up time 6CK+64ms
Тиснемо Write ALL.  Закриваємо вікно Фьюзів.

     Тепер ідемо у меню File-Load Falsh file to Buffer
Вибираємо цей самий файл прошивки у нашій папці С:\AVRPRJ\EXP1\EXP1\Debug ы натискаэмо Відкрити. 
Все, наш файл у буфері, тепер треба прошити його в МК.
Ідемо у Command - Write flash buffer to chip. Повинне з'явитися повідомлення, що все ОК
І одразу на макетці запалюється перший світлодіод. УРА!!!

     Відео процесу прошивки і запуску МК:


Зміна програми

     А тепер знову відкриємо АТМЕЛ СТУДІО і змінимо нашу програму наступним чином:
     Скачати АСМ файл з кодом ТУТ
Тобто ми змінили у головному циклі прграми команду 

:ldi r16,1; Записуємо в регістр РРЗП r16 двійкове число 1 (00000001 в двійковій системі)
на
in r16, PINB; Завантажуємо в регістр РРЗП r16 значення з регістра даних порта В.

Команда IN [РРЗП],[СЛУЖБОВИЙ РЕГІСТР], виводить значення, що міститься  у службовому регістрі в  РРЗП. Працює з усіма РРЗП. Є зворотньою до команди OUT.

     Тобто, фактично, ми зчитали значення входу (порт Б) і видали його на вихід (у порт А).
Компілюємо програму (Build - Build Solution або  F7.

Можна запустити Debug і спробувати прогнати його покроково, При цьому можна вручну виставити значення у PINB, клацаючи по квадратикам цього порта у IO View - PORTB.

    Повторюємо процедуру прошивки, не чіпаючи фьюзів. Можна перед прошивкою зробити Command-Erase Chip у  Khazama AVR Programmer.
Після чого виконуємо File-Load Falsh file to Buffer  і  Command - Write flash buffer to chip.

    Тепер наша плата не просто світить світлодіодом, вона реагує на натискання кнопок, гасячи світлодіоди з 1 по 5-ий що відповідають натиснутій кнопці. Чому так: 
Справа в тому, що ми виставили підтягуючі резистори на ножках 0...4 порта В, а отже, коли ножка вільна, на ній буде лог.1 (+U живл.). Тобто без натиснутих кнопок у у регістрі PINB буде значення 0b00011111. А при натисканні кнопки, вона замикає вивід порта на землю (див. схему макетної плати). Тому напруга на відповідному виводі стає рівна 0, що інтерпретується як лог.0, він і записується у відповідний біт регістра PINB.

Відео роботи зміненої програми:



     Отже ми навчилися:
1. Створювати проект в АТМЕЛ СТУДІО
2. Вивчили команди асемблера, що найчастіше зустрічаються при роботі з портами вводу-виводу
3. Написали першу програму-прошивку для нашого МК.
4. Прошили МК

Немає коментарів:

Дописати коментар