Проста програма для avr мікроконтролера на мові Сі

У минулій статті ми розібрали будову програми на AVR Ассемблері, зібрали нескладну схему і виконали прошивку мікроконтролера. До микроконтроллеру були підключені два світлодіоди, які ми змусили поперемінно мигати.

Тут ми розберемо приклад програми для AVR мікроконтролерів на мові Сі (C), яка буде використовувати ту ж принципову схему що і в прикладі з програмою на Асемблері, так що для роботи нам знадобиться той-же макет що і в минулій статті. Блимати світлодіоди ми змусимо не просто поперемінно, а трошки по іншому і з додатковими затримками за часом.

Коротко про мову програмування Сі

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

При розробці програм на мові Сі для AVR мікроконтролерів використовується набір бібліотек avr-libc і компілятор avr-gcc, з установкою яких в Linux ми вже розібралися в одній з минулих статей.

Вихідний код програми на мові Сі

Цілком може бути що ви ніколи не писали програм на мові Сі - в цьому немає нічого страшного. Для того щоб написати першу програму на AVR C і провести з нею експерименти цілком достатньо базових знань по роботі з консоллю в Linux. Пізніше ви самі зможете знайти відсутню інформації та вивчити все необхідне самостійно.

Наведений нижче код програми на Сі виконуватиме наступні дії (алгоритм дій):

  • запалити світлодіод 1 і погасити його з невеликою затримкою (два рази поспіль);
  • виконати більш тривалу затримку;
  • запалити світлодіод 2 і погасити його з невеликою затримкою (два рази поспіль);
  • Почати все спочатку.

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

Рядок "#include "Проводить підключення файлу" io.h "до поточного файлу вихідного коду, а рядок" #include "- підключає файл" delay.h ".

Дізнатися де розміщуються дані файли в Linux можна за допомогою команди "locate". Наприклад виконаємо пошук шляхів де розміщуються файли "io.h" і Отфильтруем результати що містять поєднання "avr":

В результаті отримаємо список шляхів до всіх файлів де в імені зустрічається "io.h", а також шлях містить підрядок "avr":

Тут ми можемо бачити що потрібний нам файл знаходиться по шляху "/usr/lib/avr/include/avr/io.h". Подивившись його вміст можна побачити що він містить в собі включення інших файлів з визначеннями (AVR device-specific IO definitions), які в свою чергу залежать від обраного нами типу мікроконтролера. Тип мікроконтролера (MCU Type) в даном випадку вказується як параметр "-mmcu = atmega8" (для ATmega8) при виклику команди-компілятора "avr-gcc".

У моєму випадку для мікроконтролера ATmega8 через файл "io.h" підключається наступний файл - "iom8.h" (Input Output Mega8), в ньому зберігаються всі визначення таких змінних як PD0, PD1, PB8, DDRD, DDRB, RAMSTART, RAMEND і багато всього іншого.

Також використовуючи команду "cat" можна вивести тільки ті рядки, які містять в файлі вказане поєднання символів або слово:

Дана команда виведе ось такий текст:

Таким чином можна подивитися які є константи і визначення в бібліотеці avr-gcc для роботи з операціями вводу-виводу (Input-Output), їх значення та багато іншого для вашого типу мікроконтролера!

Файл "delay.h" містить в собі визначення функцій затримки, зокрема там міститься код функції "_delay_ms", яку ми будемо використовувати в прикладі. Для прорахунку тимчасової затримки такі функції використовують константу "F_CPU", яку ми оголосили раніше на початку коду.

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

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

У рядку "int delay_ms_1 = 100;" ми оголосили нову змінну "delay_ms_1" з типом "int" (Integer, Цілий тип, значення від -32768 до 32767) і привласнили їй значення 100. Служить вона в нашій програмі для установки затримки в мілісекундах при мерехтінні кожного з світлодіодів.

У наступному рядку "int delay_ms_2 = 300;" ми також виконали ініціалізацію змінної, яка буде служити для установки часу затримки між миготінням окремих світлодіодів - 300 мілісекунд.

Далі йде команда "DDRD | = (1 <

Наступна команда ідентична попередньої за винятком того що вона встановлює на висновок канал PD1 порту DDRD.

До каналів PD0 і PD1 (ніжки 2 і 3 чіпа) у нас підключені світлодіоди, світінням яких ми і будемо управляти.

Рядком "PORTD | = (1 <

Далі ми виконуємо невелику затримку за часом "_delay_ms (delay_ms_1);" викликаючи функцію _delay_ms і передавши їй як аргумент змінну delay_ms_1, яка вже містить число 100.

Рядком "PORTD =

(1 <

(1 <

(1 <

"(Зміна всіх бітів на протилежні).

У наступних рядках ми знову виконуємо установку і скидання біта PD0 в регітре порту PORTD зі встановленою затримкою "delay_ms_1", ніж ми змушуємо світлодіод підключений до каналу PD0 запалитися і згаснути (майнути, blink).

Рядком "_delay_ms (delay_ms_2);" виконується більш тривала затримка за часом з використанням значення змінної "delay_ms_2" яка вище отримала значення 300 (затримка в 300 мілісекунд).

Далі ми двічі виробляємо установку і скидання біта PD1 (2-й біт в байті регістра) в регістрі порту PORTD, ніж змушуємо миготіти світлодіод що підключений до каналу PD1 порту PORTD мікроконтролера.

По завершенню наведених команд все починається знову в нескінченному циклі "while (1)".

Найскладніше до розуміння тут це, мабуть, робота з установкою потрібних бітів в портах. Більш детально дана тема висвітлена в статті: Робота з регістрами AVR мікроконтролера на Сі, бітові операції.

Компіляція і прошивка програми в МК

Для компіляції програми збережемо вихідний код в файлі під назвою "leds_blinking.c". Якщо у вас вже набудувати середовище Geany то для компіляції досить натиснути на панелі інструментів кнопку "Compile". Для компіляції файлу з програмою на Сі в консолі потрібно виконати команду:

В результаті роботи, якщо немає помилок, отримаємо об'єктний файл leds_blinking.o з якого нам потрібно витягти необхідні дані для прошивки нашого мікроконтролера (в моєму випадку ATmega8, параметр "-mmcu = atmega8").

Для вилучення даних та побудови файлу прошивки в форматі Intel Hex потрібно натиснути в Geany кнопку "Build". З консолі отримати потрібний файл можна за допомогою команди:

Тепер, коли у нас є файл з прошивкою в форматі Intel HEX залишиться записати його вміст (прошити) у флеш-пам'яті мікроконтролера, виконати цю операцію можна натиснувши в підготовленої нами середовищі Geany кнопку "Run or view current file" (Execute). В консолі виконати прошивку можна за допомогою avrdude командою (для ATmega8 параметр "-p m8", програматор USBAsp "-c usbasp"):

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

Бажано виконувати всі кроки (компіляція + побудова hex-файлу + прошивка) по черзі і вести спостереження за інформацією що з'являється в консолі або на інформаційній панелі Geany. Це допоможе виявити помилки і зауваження якщо щось не буде працювати так як треба.

Документація по мові Сі і AVR Сі

Брайан Керниган і Dennis Ritchie - Мова програмування C: brian-kernighan-and-dennis-ritchie-c-language.pdf.zip (2,1Мб, PDF).

Герберт Шілдт - Повний довідник по C: gerbert-shildt-c-complete-guide.zip (912Кб, HTML).

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

За наведеною вище посиланням можна почитати документацію (англійською мовою) прямо на сайті або ж завантажити її одним файлом в форматах HTML і PDF, там є вся необхідна інформація щодо користування бібліотеки avr-libc для програмування AVR мікроконтролерів.

висновок

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

Схожі статті