Лабораторна робота №2
ПРОГРАМУВАННЯ БІЖУЧОГО РЯДКА З ВИКОРИСТАННЯМ МІКРОКОНТРОЛЕРА AVR
Мета роботи: набути навичок програмування мікроконтролерів AVR. Закріпити вміння програмування мікроконтролерів на прикладі програмування біжучого рядка.
Теоретичні відомості
АVR – це нове сімейство 8-розрядних RISC-мікроконтролерів фірми Atmel. Ці мікроконтролери дозволяють вирішувати безліч задач вбудованих систем. Вони відрізняються від інших розповсюджених у даний час мікроконтролерів більшою швидкістю роботи, більшою універсальністю. Швидкодія даних мікроконтролерів дозволяє в ряді випадків застосовувати їх у пристроях, для реалізації яких раніше можна було застосовувати тільки 16-розрядні мікроконтролери, що дозволяє відчутно знизити ціну готової системи. Крім того, мікроконтролери АVR дуже легко програмуються – найпростіший програматор можна виготовити власноруч протягом 30 хвилин.
За заявою фірми-виробника мікроконтролерів (www.atmel.com) мікроконтролери сімейства АVR можна перепрограмувати до 1000 разів, причому безпосередньо в зібраній схемі. Все це робить мікроконтролери АVR дуже привабливими для створення нових розробок.
Фірма Atmel випускає великий спектр 8-розрядних мікроконтролерів, серед яких сімейство АТ89 з вбудованою програмованою флеш-пам’яттю та мікроконтролери сімейства АТ90 на базі поліпшеної RISC архітектури.
Заслуговують на увагу нові мікроконтролери сімейств ATtiny і АТMЕGА на базі AVR архітектури.
Крім того, що мікроконтролери сімейства ATtiny мають зменшений обсяг вбудованої флеш-пам’яті (від 1 до 2 кбайт), у кожній модифікації випускаються три версії, що відрізняються напругою живлення і тактовою частотою. Наприклад, версії ATtiny12 мають діапазон тактової частоти від 0 до 1 Мгц, від 0 до 4 Мгц і 0 до 8 Мгц відповідно при напрузі живлення від 1,8 до 5,5 В, від 2,7 до 5,5 В і від 4,0 до 5,5 В. Тільки ATtiny22 має RAM-пам'ять даних обсягом 128 байт. У ATtiny15 реалізований 10-розрядний АЦП (4 канали). Деякі модифікації ATtiny мають вбудовану систему перезапуску при зниженні напруги живлення.
Основна відмінність мікроконтролерів АТMЕGА (АТMЕGА83/103/161/ 163) – збільшений обсяг вбудованої пам'яті (АТMЕGА 103 має 128 кбайт флеш-пам’яті і 4 кбайта RAM-пам'яті) і розширений набір периферійних пристроїв. Як і в ATtiny, у модифікаціях АТMЕGА передбачені версії з різною тактовою частотою і напругою живлення. При діапазоні напруги живлення від 2,7 до 3,6 В і від 4,0 до 5,5 В діапазон тактових частот складає відповідно від 0 до 4 Мгц і від 0 до 6 Мгц.
Розглянемо більш детально один з мікроконтролерів сімейства ATMEGA, а саме ATMEGA 16, який і пропонується використовувати в лабораторній роботі.
Основні характеристики мікроконтролера ATMEGA 16:
AVR RISC-архітектура – архітектура високої продуктивності та малого споживання;
система команд містить 130 інструкцій, більшість яких виконується за один машинний цикл;
єдиний 16-розрядний формат команд;
продуктивність 16 MIPS на частоті 16 Мгц;
наявність апаратного помножувача;
16 Кбайт Flash ПЗУ програм, з можливістю до 1000 циклів стирання/запису;
512 байт EEPROM даних, з можливістю до 100000 циклів стирання/запису;
1 Кбайт оперативної пам'яті (SRAM);
можливість програмування безпосередньо в цільовій системі через послідовні інтерфейси SPI і JTAG;
можливість самопрограмування;
можливість внутрішньосхемного налагодження у відповідності зі стандартом IEEE 1149.1 (JTAG);
різні способи синхронізації;
режим зниженого енергоспоживання;
детектор зниження напруги живлення;
програмне зниження частоти тактового генератора;
21 джерело переривань (внутрішніх і зовнішніх);
багаторівнева система переривань, підтримка черги переривань;
можливість захисту від несанкціонованого читання та модифікації пам'яті програм і даних;
можливість читання пам'яті програм під час її запису;
два 8-розрядних таймера/лічильника;
сторожовий таймер WDT;
чотири канали генерації вихідних шим-сигналів;
аналоговий компаратор;
8-канальний 10-розрядний АЦП як з несиметричними, так і з диференціальними входами;
повнодуплексний універсальний синхронний/асинхронний приймач-передавач USART;
послідовний синхронний інтерфейс SPI, що використовується також для програмування Flash-пам'яті програм;
послідовний двохпровідний інтерфейс TWI (аналог I2C);
32 програмовані лінії введення/виведення з рівнями ТТЛ, на ці лінії виведена також підтримка периферійних функцій;
напруги живлення 2,7 ... 5,5 В.
Ядро мікроконтролерів AVR виконане за вдосконаленою RISC-архітектурою (Enhanced RISC). Арифметико-логічний пристрій (АЛУ), що виконує всі обчислення, підключений безпосередньо до 32 робочих регістрів, об'єднаних в регістровий файл. Завдяки цьому АЛУ виконує одну операцію за один машинний цикл. Практично кожна з команд (за винятком команд, у яких одним з операндів є 16-розрядна адреса) займає одну комірку пам'яті програм.
В мікроконтролерах AVR реалізована Гарвардська архітектура, яка характеризується роздільною пам'яттю програм і даних, кожна з яких має власні шини доступу до них. Така організація дозволяє одночасно працювати як з пам'яттю програм, так і з пам'яттю даних. Розділення шин доступу дозволяє використовувати для кожного типу пам'яті шини різної розрядності, причому способи адресації і доступу до кожного типу пам'яті також різні.
Ще одним рішенням, спрямованим на підвищення швидкодії, є використання технології конвеєризації. Конвеєризація полягає в тому, що під час виконання поточної команди проводиться вибірка з пам'яті і дешифрування коду наступної команди. Причому тривалість машинного циклу мікроконтролерів AVR складає всього один період тактового генератора.
Файл регістрів швидкого доступу містить 32 8-розрядних робочих регістра загального призначення пов'язаних безпосередньо з ALU. За один тактовий цикл з файлу регістрів вибираються два операнди, виконується операція і результат знову повертається у файл регістрів.
Шість із 32 регістрів можуть бути використані як три 16-розрядних регістра покажчика непрямої адресації адресного простору даних, що забезпечують ефективне обчислення адрес. Один з цих покажчиків адреси використовується, також, як покажчик адреси для функції безперервного перегляду таблиць. Ці 16-розрядні додаткові регістри позначаються як X-регістр, Y-регістр і Z-регістр.
На додаток до операцій з регістрами, регістровий файл може використовуватися і для звичайної адресації пам'яті. Це пояснюється тим, що файл регістрів розташовується за 32-ма молодшими адресами простору даних, і до них можна звертатися, як до звичайних комірок пам'яті.
Простір пам'яті I/O містить 64 адреси периферійних функцій CPU таких як: регістри управління, таймери/лічильники, аналого-цифрові перетворювачі та інші I/O функції. До пам'яті I/O можна звертатися безпосередньо або як до осередків простору пам'яті з відповідним адресами файлу регістрів.
В процесі обробки переривань та викликів підпрограм адреса повернення лічильника команд (PC) зберігається в стек. Стек розміщується в SRAM даних. Всі програми користувача в підпрограмах повернення повинні ініціалізувати покажчик стека (SP).
AVR архітектура підтримує п'ять різних режимів адресації байт SRAM даних.
Гнучкий модуль обробки переривань має в просторі I/O свій керуючий регістр з додатковим бітом дозволу глобального переривання в регістрі статусу. Всі переривання мають свої вектори переривання в таблиці векторів переривання, які розташовуються на початку пам'яті програм. Пріоритети переривань відповідають положенню векторів переривань – переривання з найменшою адресою вектора має найвищий пріоритет.
Опис лабораторного стенду
Лабораторний стенд дозволяє контролювати роботу мікроконтролера за допомогою матриці світлодіодів, підключеної до портів мікроконтролера. Невід'ємною частиною лабораторного стенду є програматор, який дозволяє програмувати більшість представлених на російському та українському ринках мікросхем пам'яті і мікроконтролерів сімейства AVR. Основна особливість лабораторного стенду полягає в тому, що він працює окремо і незалежно від програматора, а програматор підключається для того щоб записати робочу програму у мікроконтролер. Через програматор здійснюється стикування USB-порту IBM PC-сумісного комп'ютера зі стендом, розробленим під конкретний тип мікросхем.
Зовнішній вигляд зібраного програматора представлений на рисунку 2.1, зовнішній вигляд лабораторного стенду – на рисунку 2.2.
/
Рисунок 2.1 – Зовнішній вигляд програматора
Для забезпечення роботи програматора можна використовувати доступне програмне забезпечення, наприклад "AVRDUDE".
AVRDUDE (USBASP_AVRDUDE_PROG) це досить потужний консольний програматор, що має GUI, призначений для програмування мікроконтролерів AVR під ОС Windows через USB порт. Основна відмінність від аналогічних програм – можливість програмування через USB порт, функція збереження всіх параметрів програмування кристалу з послідуючим їх вибором з випадаючого меню списку, висока швидкість програмування.
Для того щоб розпочати роботу з лабораторним стендом необхідно правильно з’єднати програматор зі стендом і комп’ютером, а також встановити необхідні для роботи програматора драйвера.
Програматор підключається через USB порт до комп’ютера, потім вмикається блок живлення лабораторного стенду у мережу 220 В. Лабораторний стенд з програматором готовий до роботи.
/
Рисунок 2.2 – Зовнішній вигляд лабораторного стенду
Порядок виконання роботи
Скориставшись навиками, набутими при виконанні попередньої лабораторної роботи, а також теоретичними відомостями, необхідно: зібрати стенд, написати програму відповідно індивідуальному завданню та запрограмувати мікроконтролер. Для цього треба виконати такі дії.
Запускаємо програму AVR Studio. В цій програмі, власне, буде відбуватись написання тексту робочої програми.
У головному вікні програми з’явиться вікно з назвою "Welcome to AVR Studio 4", в я кому буде запропоновано два варіанти початку роботи з програмою: створити новий проект, або відкрити готовий проект (натиснувши кнопку "Open" та вказавши повний шлях до, вже створеного проекту). Щоб створити новий проект необхідно натиснути кнопку "New Project", вибрати тип проекту "Atmel AVR Assembler" в полі "Project Type", в полі "Project Name" потрібно вказати ім’я проекту і натиснути кнопку "Next". В наступному вікні, що з’явиться, в полі "Debug Platform" вибираємо відладку для програми, наприклад "AVR Dragon", в полі "Device" знаходимо той тип мікроконтролера з яким програматор працює на даний момент (ATMEGA 16), і натискаємо на кнопку "Finish". Відкриється нове вікно, в якому здійснюється написання програми.
Після того як текст програми успішно набраний, необхідно перетворити його у машинний код. Це можна зробити натиснувши клавіші F7 на клавіатурі або скориставшись командою Build меню Build.
AVR Studio автоматично перетворить текст програми у машинний код та збереже його у файлі з розширенням .hex. На цьому етапі робота з програмою AVR Studio завершена, для того щоб записати програму у мікроконтролер необхідно скористатись програмою AVRDUDE, вікно якої зображене на рисунку 2.3.
/
Рисунок 2.3 – Вікно USBASP_AVRDUDE_PROG
Запустивши USBASP_AVRDUDE_PROG вибираємо з випадаючого меню потрібний нам мікроконтролер, в меню нижче вибираємо .hex-файл з програмою. Натискаючи на кнопку "Програмирование" даємо команду на програмування.
Якщо мікроконтролер був правильно записаний і текст програми не містить помилок, то на світлодіодній матриці лабораторного стенду ми можемо побачити результат виконання програми.
Хід роботи
1. Лістинг програми яка виводить на світлодіодну матрицю текст «ЧДТУ ФЕТ»:
#include <avr\io.h>
#include <avr\interrupt.h>
#define speed 1200 // швидкість прокрутки
#define length 55 // кількість рядків в масиві
/* визначення змінних */
unsigned int count = 0; // лічильник тактів
uint8_t line = 0; // лічильник рядків
uint8_t frame = 0; // номер рядка масиву
uint8_t shift = 0; // лічильник зсуву
char picture [length] = { // масив рядка прокрутки
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111100,
0b11111100,
0b00000000,
0b00000000,
0b11111100,
0b11111100,
0b11111111,
0b00111100,
0b00100100,
0b00100100,
0b00000000,
0b00000000,
0b11111111,
0b11100001,
0b11000000,
0b11011110,
0b00000000,
0b00000000,
0b11011110,
0b11000000,
0b11100001,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11000000,
0b10000000,
0b00101111,
0b01100000,
0b11110000,
0b11111111,
0b11111100,
0b11111100,
0b00000000,
0b00000000,
0b11111100,
0b11111100,
0b11111111,
0b00011111,
0b00000000,
0b11011110,
0b11011101,
0b00000011,
0b00011111,
0b11111111,
0b00000000,
0b00000000,
0b11101111,
0b11100000,
0b11110000,
};
/* обробка переривання */
ISR(TIMER0_OVF_vect) { // переривання по переповненню таймера
PORTC = line; // передача на дешифратор номера рядка
frame = (length - 1) + 7 - line - shift; // формування номера рядка масиву
if (frame > (length-1)) frame -= length; // переведення вказівника рядка масиву на початок
PORTA = picture[frame]; // виведення на матрицю рядка
line++; // інкрементування лічильника рядків
if (line == 8) line = 0; // обнуління лічильника при переповненні
count++; // інкрементування лічильника тактів
if (shift == (length - 1)) shift=0; // обнуління лічильника зсуву
if (count == speed) // задаємо зсув
{
shift++;
count=0;
}
}
int main(void)
{
/* налаштування виводів мікроконтролера на режим виведення */
DDRA = 0xFF;
DDRC = 0xFF;
TIMSK = (1<<TOV0); // переривання по переповненню таймера
TCNT0=0x00; // обнуління регістра порівняння
TCCR0 = (1<<CS01) ; // встановлення дільника на 8
sei(); // дозвіл переривань
for(;;) { // нескінченний цикл
}
}
2. Лістинг програми яка виводить на світлодіодну матрицю текст «З НОВИМ РОКОМ»:
#include <avr\io.h>
#include <avr\interrupt.h>
#define speed 1200 // швидкість прокрутки
#define length 111 // кількість рядків в масиві
/* визначення змінних */
unsigned int count = 0; // лічильник тактів
uint8_t line = 0; // лічильник рядків
uint8_t frame = 0; // номер рядка масиву
uint8_t shift = 0; // лічильник зсуву
char picture [length] = { // масив рядка прокрутки
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b10001001,
0b01110110,
0b01110110,
0b10111101,
0b11111111,
0b00000000,
0b11111101,
0b11111011,
0b11111111,
0b10000001,
0b01111110,
0b01111110,
0b10000001,
0b11111111,
0b01111001,
0b01110110,
0b01101110,
0b00011101,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b00000000,
0b00000000,
0b11111001,
0b11100011,
0b11100011,
0b11111001,
0b00000000,
0b00000000,
0b11111111,
0b10000001,
0b00000000,
0b00111100,
0b00111100,
0b00000000,
0b10000001,
0b11111111,
0b00111110,
0b00011100,
0b11001001,
0b11100011,
0b00000000,
0b00000000,
0b11111111,
0b10000001,
0b00000000,
0b00111100,
0b00111100,
0b00000000,
0b10000001,
0b11111111,
0b11111001,
0b11110000,
0b11110110,
0b11110110,
0b00000000,
0b00000000,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b00000000,
0b00000000,
0b11111001,
0b11100011,
0b11100011,
0b11111001,
0b00000000,
0b00000000,
0b11111111,
0b00000000,
0b00000000,
0b11100011,
0b11000111,
0b00000000,
0b00000000,
0b11111111,
0b10011111,
0b00001001,
0b01100000,
0b01100110,
0b00000000,
0b00000000,
0b11111111,
0b10000001,
0b00000000,
0b00111100,
0b00111100,
0b00000000,
0b10000001,
0b11111111,
0b00000000,
0b00000000,
0b11100111,
0b01100111,
0b00000000,
0b00000000,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b10001001,
0b00000000,
0b00110100,
0b00110100,
0b00111101,
};
/* обробка переривання */
ISR(TIMER0_OVF_vect) { // переривання по переповненню таймера
PORTC = line; // передача на дешифратор номера рядка
frame = (length - 1) + 7 - line - shift; // формування номера рядка масиву
if (frame > (length-1)) frame -= length; // переведення вказівника рядка масиву на початок
PORTA = picture[frame]; // виведення на матрицю рядка
line++; // інкрементування лічильника рядків
if (line == 8) line = 0; // обнуління лічильника при переповненні
count++; // інкрементування лічильника тактів
if (shift == (length - 1)) shift=0; // обнуління лічильника зсуву
if (count == speed) // задаємо зсув
{
shift++;
count=0;
}
}
int main(void)
{
/* налаштування виводів мікроконтролера на режим виведення */
DDRA = 0xFF;
DDRC = 0xFF;
TIMSK = (1<<TOV0); // переривання по переповненню таймера
TCNT0=0x00; // обнуління регістра порівняння
TCCR0 = (1<<CS01) ; // встановлення дільника на 8
sei(); // дозвіл переривань
for(;;) { // нескінченний цикл
}
}
3. Лістинг програми яка виводить на світлодіодну матрицю анімовану картинку «смайлик»:
#include <avr\io.h>
#include <avr\interrupt.h>
#define speed 10000 // швидкість прокрутки
#define length 32 // кількість рядків в масиві
/* визначення змінних */
unsigned int count = 0; // лічильник тактів
uint8_t line = 0; // лічильник рядків
uint8_t frame = 0; // номер рядка масиву
uint8_t shift = 0; // лічильник зсуву
char picture [length] = { // масив рядка прокрутки
0b11000011,
0b10111101,
0b01011010,
0b01011110,
0b01011110,
0b01011010,
0b10111101,
0b11000011,
0b11000011,
0b10111101,
0b00111010,
0b01011110,
0b01011110,
0b00111010,
0b10111101,
0b11000011,
0b11000011,
0b10111101,
0b01011010,
0b01011110,
0b01011110,
0b01011010,
0b10111101,
0b11000011,
0b11000011,
0b10111101,
0b01101010,
0b01011110,
0b01011110,
0b01101010,
0b10111101,
0b11000011,
};
/* обробка переривання */
ISR(TIMER0_OVF_vect) { // переривання по переповненню таймера
PORTC = line; // передача на дешифратор номера рядка
frame = (length - 1) + 8 - line - shift; // формування номера рядка масиву
if (frame > (length-1)) frame -= length; // переведення вказівника рядка масиву на початок
PORTA = picture[frame]; // виведення на матрицю рядка
line++; // інкрементування лічильника рядків
if (line == 8) line = 0; // обнуління лічильника при переповненні
count++; // інкрементування лічильника тактів
if (count == speed) // задаємо зсув
{
shift +=8;
count=0;
}
if (shift > (length - 1)) shift=0;
}
int main(void)
{
/* налаштування виводів мікроконтролера на режим виведення */
DDRA = 0xFF;
DDRC = 0xFF;
TIMSK = (1<<TOV0); // переривання по переповненню таймера
TCNT0=0x00; // обнуління регістра порівняння
TCCR0 = (1<<CS01) ;// встановлення дільника на 8
sei(); // дозвіл переривань
for(;;) { // нескінченний цикл
}
}
Висновок. В даній лабораторній роботі ми набули навичок програмування мікроконтролерів AVR. За допомогою AVR Studio, пишемо і перевіряєм на наявність помилок програму для мікроконтролера ATMEGA 16. Після того як текст програми успішно набраний, необхідно перетворити його, скориставшись командою Build меню Build, у машинний код. AVR Studio автоматично перетворює текст програми у машинний код та зберігає його у файлі з розширенням .hex. Щоб записати програму у мікроконтролер використовуєм програму AVRDUDE. Запускаємо USBASP_AVRDUDE_PROG, вибираємо з мікроконтролер ATMEGA 16, та відкриваєм .hex-файл з програмою. Натискаючи на кнопку "Програмирование" даємо команду на програмування. На світлодіодній матриці лабораторного стенду ми бачимо результат виконання програми.