![]() | 1 2 3 4 Ім'я файлу: РобототехникаЛабораторныеБаза_4_5_6.pdf Розширення: pdf Розмір: 3063кб. Дата: 21.10.2022 скачати Методичні вказівки до виконання лабораторних робіт з курсу «Робототехнічні системи» базова частина 2 Зміст Вступ 2 Лабораторна робота №4 (переривання від таймер-лічильників) 9 Лабораторна робота №5 (зовнішні переривання) 23 Лабораторна робота №6 (інтерфейс USART/UART) 36 2 Вступ Загальні правила оформлення звітів з лабораторних робіт Лабораторна робота потрібна містити титульний лист згідно встановленого зразка (див. сторінку 8) на якому обов’язково потрібно вказати номер лабораторної роботи, свій варіант (згідно журналу викладача), прізвище з ініціалами та номер групи. Усі програми мають бути написані мовою С(С++) та мають містити номера строк. В лабораторних роботах 1 – 5 дозволяється, за потреби, використовувати «ардуінівські» функції роботи з USART (serial Monitor). Якщо необхідно, то звіт має містити електричні принципові та монтажні схеми які потрібні бути оригінальними, тобто створеними власноруч. Тип мікроконтролера вказує викладач. Наприкінці звіту потрібно зробити висновки. Опис мікроконтролерів В цьому курсі ми будемо вивчати базові концепції керування робототехнічними системами на прикладі мікроконтролерів ATmega328 та ATmega2560. Для того щоб зосередитись безпосередньо на можливостях цих мікроконтролерів та для простоти підключення і програмування будемо використовувати платформи Arduino UNO (ATmega328) та Arduino MEGA (ATmega2560). Для програмування вказаних Arduino платформ нам знадобиться програмне середовище Arduino IDE яке можна вільно завантажити та встановити на своєму комп’ютері. Відповідність між ніжками мікроконтролерів та пінів на платформі Arduino представлено на рис. 1 та рис.2. Пояснимо один дуже важливий момент. Цифрові піни платформи Arduino будемо позначати як D0, D1 і так далі, аналогові піни – А0, А1 … Таким чином, наприклад, пін D8 на платформі Arduino UNO відповідає піну РВ0 мікроконтролера ATmega328, а той же самий пін D8 платформи Arduino MEGA відповідає піну РH5 мікроконтролера ATmega2560. Також пін А0 на Arduino UNO відповідає піну РС0 мікроконтролера ATmega328, а на Arduino MEGA – PF0 (дивись рисунки вкладки). 3 Рис. 1. Мікроконтролер ATmega328. 4 Рис. 2. Мікроконтролер ATmega2560. 5 Платформи Arduino з’єднуються з комп’ютером за допомогою кабелю типу USB A-B по якому відбувається живлення мікроконтролерів та необхідної периферії, а також програмування. Макетна плата Якщо згідно з завданням лабораторної роботи треба зібрати електричну схему, це потрібно робити на макетній платі. В лабораторії рекомендовано використовувати плату на 830 точок з кроком 2,54 мм (0,1 дюйма). Рис. 3. Зовнішний вигляд макетної плати. В отворах розташовані контактні роз’єми для встановлення деталей з контактами діаметром до 0,8 мм. Макетна плата має дві шини живлення (горизонтальні рядки які позначені синьою «-» і червоною «+» лініями) та вертикальні рядки з’єднані по 5 штук. Роз'єми та шини виконані у вигляді металевих контактів, вставлених зі зворотного боку плати, та закритих захисною наклейкою. На рис. 4 зображено з’єднання роз’ємів. Рис. 4. Структура макетної плати. 6 Резистори та їх кольорове маркування На сайті https://www.pc-control.co.uk/resistor_code.htm знаходимо наступну схему Рис. 5. Кольорове маркування резисторів. За допомогою цієї схеми можна визначати номінал резисторів які маркіруються кольоровими кільцями. Але ми здебільше будемо користуватись резисторами на 510 Ом та на 10 кОм (дивись рис.6). Рис. 6. Резистори. Тому рекомендується запам’ятати як виглядають ці резистори. Конденсатори Також в цьому курсі ми будемо використовувати керамічні конденсатори на 0,1 мкФ який маркірується як 104, та на 1 мкФ – маркіровка 105 (дивись рис.7). Рис. 7. Конденсатори. 7 Код 104 означає 10×10000 пФ = 10 5 пФ = 0,1 мкФ, таким же чином розшифровується код 105, маємо 10×100000 пФ = 10 6 пФ = 1 мкФ. Кнопка На рис 8. ми бачимо зовнішній вигляд кнопки та її принципову електричну схему. Звідси випливає, що ми можемо використовувати будь яку пару не замкнених виводів. Рис. 8. Кнопка та її електрична схема. Світлодіод Для наочності керування GPIO мікроконтролера дуже часто використовують світлодіоди. Нагадаємо, що світлодіоди завжди підключаються до пінів мікроконтролера через обмежуючий струм резистор, для цього ми будемо використовувати резистор на 510 Ом. Для того щоб світлодіод випромінював світло анод світлодіоду потрібно підключити до високого, а катод до низького потенціалів. Анод світлодіоду має більшу довжину ніж катод, або колба світлодіоду зі сторони катоду має зріз (див. рис.9). Позначення світлодіоду на принциповій електричній схемі та на монтажній схемі зображено на рис.10. Рис. 9. Світлодіод. Рис. 10. Позначення світлодіоду на принципових та монтажних схемах. 8 Міністерство освіти і науки України Харківський національний університет ім. В.Н. Каразіна Факультет комп’ютерних наук Кафедра теоретичної та прикладної системотехніки Лабораторна робота № З навчальної дисципліни “ Робототехнічні системи” Виконав: студент групи _____ __________________ варіант № ________ Перевірив: Харків 9 Лабораторна робота №4 (переривання від таймер-лічильників) Мета лабораторної роботи Навчитися теоретично розраховувати та експериментально визначати параметри роботи переривань таймер-лічильників мікроконтролерів ATmega328 і ATmega2560 в різних режимах роботи. Теоретичні відомості Згідно з технічною документацією у мікроконтролерах реалізовані переривання від таймер-лічильників за такими подіями: - збіг таймер-лічильника з регістром порівняння; - переповнення таймер-лічильника; - захоплення таймер-лічильника. Захоплення таймер-лічильника є тільки в 16-бітних таймерах. Кількість переривань по переповненню дорівнює кількості таймер-лічильників у мікроконтролері. Кількість переривань за збігом дорівнює повній кількості каналів, в ATmega328 їх 6, в ATmega2560 - 16 (по 3 канали в 4-х шістнадцяти бітних таймерах, по 2 канали в 2-х восьми бітних таймерах). Для дозволу цих переривань використовуються регістри (Timer Interrupt Mask Register) TIMSKn, де n=0, 1, 2 для ATmega328 та n=0, 1, 2, 3, 4, 5 для ATmega2560. Структура регістрів TIMSKn для 8-бітних таймерів зображена на рис. L4_1. Рис. L4_1. Регістри TIMSKn, де n = 0 або 2. Структура регістрів TIMSKn для 16-бітних таймерів мікроконтролера ATmega2560 зображена на рис. L4_2. Рис.L4_2. Регістри TIMSKn мікроконтролера ATmega2560 (n=1,3,4,5). 10 Регістри TIMSKn для 8-бітних таймерів мікроконтролерів ATmega328 та ATmega2560 мають однакову структуру. Структура регістрів TIMSKn для 16- бітних таймерів мікроконтролерів ATmega328 та ATmega2560 відрізняється тільки тім, що таймери мікроконтролера ATmega328 не мають каналу С. Біти OCIEnx дозволяють переривання при збігу лічильного регістра з відповідним регістром порівняння, біти TOIEn дозволяють переривання при переповненні рахункового регістра, а біти ICIEn дозволяють переривання по захопленню. Всі джерела переривань можна подивитися в офіційній технічній документації в таблиці Interrupt Vectors in ATmega328 (Table 16-1) для мікроконтролера ATmega328 та в таблиці Interrupt Vectors in ATmega640/1280/1281/2560/2561 (Table 32) для мікроконтролера ATmega2560. Наведемо тут тільки існуючі переривання за таймерами (дивись таблиці L4_1 та L4_2). Таблиця L4_1. Вектори переривань за таймерами для ATmega328 Номер вектору Адреса Джерело Опис переривання 8 0x000E TIMER2 COMPA Збіг A таймера/лічильника T2 9 0x0010 TIMER2 COMPB Збіг В таймера/лічильника T2 10 0x0012 TIMER2 OVF Переповнення таймера/лічильника T2 11 0x0014 TIMER1 CAPT Захоплення таймера/лічильника T1 12 0x0016 TIMER1 COMPA Збіг A таймера/лічильника T1 13 0x0018 TIMER1 COMPB Збіг В таймера/лічильника T1 14 0x001A TIMER1 OVF Переповнення таймера/лічильника T1 15 0x001C TIMER0 COMPA Збіг A таймера/лічильника T0 16 0x001E TIMER0 COMPB Збіг В таймера/лічильника T0 17 0x0020 TIMER0 OVF Переповнення таймера/лічильника T0 Таблиця L4_2. Вектори переривань за таймерами для ATmega2560 Номер вектору Адреса Джерело Опис переривання 14 $001A TIMER2 COMPA Збіг A таймера/лічильника T2 15 $001C TIMER2 COMPB Збіг В таймера/лічильника T2 16 $001E TIMER2 OVF Переповнення таймера/лічильника T2 17 $0020 TIMER1 CAPT Захоплення таймера/лічильника T1 11 18 $0022 TIMER1 COMPA Збіг A таймера/лічильника T1 19 $0024 TIMER1 COMPB Збіг В таймера/лічильника T1 20 $0026 TIMER1 COMPC Збіг С таймера/лічильника T1 21 $0028 TIMER1 OVF Переповнення таймера/лічильника T1 22 $002A TIMER0 COMPA Збіг A таймера/лічильника T0 23 $002C TIMER0 COMPB Збіг В таймера/лічильника T0 24 $002E TIMER0 OVF Переповнення таймера/лічильника T0 32 $003E TIMER3 CAPT Захоплення таймера/лічильника T3 33 $0040 TIMER3 COMPA Збіг A таймера/лічильника T3 34 $0042 TIMER3 COMPB Збіг В таймера/лічильника T3 35 $0044 TIMER3 COMPC Збіг С таймера/лічильника T3 36 $0046 TIMER3 OVF Переповнення таймера/лічильника T3 42 $0052 TIMER4 CAPT Захоплення таймера/лічильника T4 43 $0054 TIMER4 COMPA Збіг A таймера/лічильника T4 44 $0056 TIMER4 COMPB Збіг В таймера/лічильника T4 45 $0058 TIMER4 COMPC Збіг С таймера/лічильника T4 46 $005A TIMER4 OVF Переповнення таймера/лічильника T4 47 $005C TIMER5 CAPT Захоплення таймера/лічильника T5 48 $005E TIMER5 COMPA Збіг A таймера/лічильника T5 49 $0060 TIMER5 COMPB Збіг В таймера/лічильника T5 50 $0062 TIMER5 COMPC Збіг С таймера/лічильника T5 51 $0064 TIMER5 OVF Переповнення таймера/лічильника T5 Для того щоб використовувати будь-які переривання треба підключити необхідну бібліотеку з іменами переривань #include < avr / interrupt h > Для встановлення глобального дозволу необхідно встановити або скинути біт загального дозволу переривань (Global Interrupt Enable bit) регістра стану ядра, який називається SREG (Status Register). Робити це рекомендується використовуючи макрос-функції: sei(); //дозволити всі переривання cli(); //заборонити всі переривання Також необхідно включити відповідний біт або біти регістрів TIMSKn (дивись рис. L4_1 або рис. L4_2 ). Дуже важливим кроком при використанні переривань є підготовка обробника переривань. Тобто необхідно написати функцію яка буде визиватися при виникненні той чи іншої події. Для того щоб компілятор зрозумів, що ця 12 функція і є обробник переривань необхідно виконати деякі умови. Загальні правила при написанні процедури обробки переривань наступні: 1) обробник переривання не може нічого приймати в якості аргументу, а також не може нічого повертати; 2) перед оголошенням обробника необхідно вказати, що він є процедурою обробки переривання; 3) обробник переривання повинен виконуватися, як можна швидше. У середовищах розробки Atmel Studio, AVR Studio (AVR GCC), Arduino IDE опис обробника переривань можливий або перед функцією main, або після і уявляє собою наступну конструкцію: ISR(SOURCE_vect) { // Тіло обробника переривання } де SOURCE це ім'я джерела вектору переривання згідно з таблицями L4_1, або L4_2. Наприклад, нам потрібно написати обробник переривання при виникненні події переповнення таймера/лічильника T5. У таблиці L4_2 знаходимо назву джерела TIMER5 OVF (вектор №51), дописуємо до нього суфікс _vect, а між словами в імені джерела переривань ставимо підкреслення: TIMER5_OVF_vect Тоді структура обробника цієї події буде виглядати як: ISR(TIMER5_OVF_vect) { // Тіло обробника переривання } Зауважимо, якщо в тілі переривання змінюється значення деякої глобальної змінної, то вона повинна бути оголошена з модифікатором volatile В якості прикладу використання переривання по переповненню рахункового регістру таймер-лічильника напишемо програму яка буде змінювати стан піна А7 кожні 20,48 мілісекунд. Для цього задіймо п’ятий таймер-лічильник в 13 звичайному режимі, тобто в режимі №0. Як було сказано раніше, формули (2.1) або (3.1), кожний такт таймеру триває нc N t такт 5 , 62 . Врахуємо, що в цьому режимі таймер рахує від 0 до 65535, тобто робить 65536 тактів. Встановивши дільник рівним одиниці отримуємо, що таймер буде переповнюватись кожні мс нc t 096 , 4 5 , 62 65536 . (4.1) Поділимо заданий час 20,48 мс на час переповнення таймеру 4,096 мс і знайдемо, що за вказаний час таймер переповниться 5 разів. Це означає, що в програмі потрібно рахувати кількість переповнень і як тільки буде досягнуте таке значення інвертувати стан відповідного піна. Таким чином маємо наступну програму. progL4_1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #define F_CPU 16000000UL // частота - 16MHz #include < avr / io h > // Бібліотека вводу/виводу #include < avr / interrupt h > // Бібліотека імен переривань volatile uint8_t Counter = 0; int main( void ){ //ATmega2560 DDRF |= (1 << DDF7); //PF7=A7 як ВИХІД //Режим NORMAL за замовчуванням TCCR5B |= (1 << CS50); //дільник N=1 TIMSK5 |= (1 << TOIE5); //дозволяємо переривання по переповненню sei(); //дозволяємо глобальні переривання while (1){}; //основна програма } ISR(TIMER5_OVF_vect){ //обробник переривання Counter ++ ; if (Counter == 5){ PORTF ^= (1 << PORTF7); Counter = 0; } } Завантаживши progL4_1 отримуємо наступну часову діаграму. Рис .L4_3 . Часова діаграма після завантаження progL4_1 Проаналізувавши програму progL4_1 бачимо, що керувати часом переповнення таймеру можливо тільки налаштуванням відповідного дільника, а це означає, що час виклику обробника переривань по переповненню можна змінювати лише з великим кроком. 14 У цьому пункті ми підрахуємо мілісекунди, в деякому сенсі створимо аналог функції millis() з мови Wiring. Декларуємо змінну millisCounter яка буде збільшувати своє значення кожну мілісекунду. Так як змінна глобальна, то ми можемо зчитати її значення або змінити його в будь-якому місці програми і тому необхідно вказати модифікатор volatile . Виберемо режим СТС роботи таймеру та значення дільника 64. Частота з якою таймер буде досягати значення ТОР у режимах СТС визначається формулою (3.5), тоді час досягнення ТОР після скидання рахункового регістру розраховується як clk OCnx f TOP N f T t ) 1 ( 2 1 2 . (4.1) Нам треба, щоб час скидання таймеру відбувався кожну мілісекунду, тобто c t 3 10 . Тоді, у нашому випадку, знаходимо 250 64 10 16 10 1 6 3 N f t TOP clk . (4.2) Звідси бачимо, що значення ТОР яке необхідне помістити в порівняльний регістр дорівнює 250 – 1 = 249. Напишемо наступну програму в якій задіймо п’ятий таймер та канал С. progL4_2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #define F_CPU 16000000UL // вкажемо компілятору частоту #include < avr / io h > //Бібліотека вводу/виводу AVR #include < util / delay h > #include < avr / interrupt h > // Бібліотека імен переривань volatile unsigned long millisCounter=0; int main( void ) { Serial begin (9600); TCCR5A = 0; TCCR5B |= (1 << WGM52)|(1 << WGM53); //режим №12 СТС TCCR5B |= (1 << CS51) | (1 << CS50); // дільник 64 ICR5 = 250-1; // переривання виконується раз в мілісекунду TIMSK5 |= (1 << OCIE5C); //Дозволяемо переривання TIMER5_COMPC_vect sei(); // Дозволяемо глобальні переривання while (1) { Serial println (millisCounter); _delay_ms(100); } } ISR(TIMER5_COMPC_vect){ millisCounter ++ ; } 15 Цикл while (строки 16-19) в цій програмі можна було залишити порожнім, але ми для наочності зробили вивід значення змінної millisCounter в монітор порту скориставшись для простоти функціями мови Wiring Serial begin (8- строка) и Serial println (17-строка). Якщо в програмі progL4_2 було б обрано режим СТС №4, то значення ТОР треба було б помістити в регістр OCR5A. Напишемо тепер програму, яка буде вимірюватиме час натискання на кнопку за допомогою переривання по захопленню. Режим захоплення означає, що при настанні деякої події, значення рахункового регістра TCNTn захоплюється регістром ICRn і зберігається в ньому до наступної події. Керування режимом захоплення здійснюється бітами ICNCn, ICESn регістра TCCRnB (див. рис. L3_2). За допомогою біта ICESn встановлюється активний фронт на піні ICPn. Якщо ICESn = 0, то активний негативний фронт сигналу, якщо ICESn = 1 – позитивний фронт. Якщо біт ICNCn =0 (скинуто) схема придушення перешкод відключена і захоплення відбувається по першому активному фронту. Якщо біт ICNCn =1 (встановлено) схема придушення перешкод включена і захоплення відбувається по четвертому поспіль активному фронту. При використанні переривання по захопленню необхідно встановити біт ICIEn регістра TIMSKn (див. рис L4_2 ). Згідно з технічною документацією піни ICPn для мікроконтролера ATmega328: ICP1 = PB0 (D8); та ATmega2560: ICP1 = PD4 (D-), ICP3 = PE7 (D-), ICP4 = PL0 (D49), ICP5 = PL1 (D48). Для захоплення сигналу з виводу ICPn, цей пін повинен бути налаштований як ВХІД (розряд регістра DDRx, відповідний піну, повинен бути скинуто у «0»). Якщо ж він буде налаштований як ВИХІД, захоплення можна буде здійснювати програмно, керуючи відповідним розрядом порту. 16 Для виміру часу натискання кнопки будемо використовувати п’ятий таймер. Підключімо кнопку за наступною схемою (див. рис. L4_4 ), де для боротьби з брязкотом контактів застосовано прості- ший RC фільтр. Також будемо вва- жати, що пін PL1 налаштовано на ВХІД і підтягнуте програмними засо- бами до +5 вольт. Тоді момент натискання кнопки буде відповідати негативному фронту, а відпускання – позитивному. Таким чином, нам потрібно виміряти час присутності на піні ICP5 логічного нуля. Для цього зробимо наступне: а) дозволимо запуск переривання по захопленню таймера командою TIMSK5 |= (1 << ICIE5); б) дозволимо глобальні переривання sei(); в) опишемо обробник переривання по захопленню (див. таблицю L4_2) ISR(TIMER5_CAPT_vect){ //обробник переривання по захопленню } Оголосимо 16-бітну без знакову змінну з іменем 1 2 3 4 |