Прості пристрої - WinAVR консольне введення-виведення

winavr
Методика «програмування кліками мишки» настільки міцно в'їлася у свідомість сучасних користувачів комп'ютерів, що багато програмістів мікроконтролерів-початківців вважають WinAVR дуже складним і незручним, а CVAVR навпаки — дуже простим і зручним. Моя думка про CVAVR негативна, але зараз не про це. Я спробую показати, що вирішення багатьох типових завдань WinAVR може бути нітрохи не складніше, ніж використання плодів Code Wizard з CVAVR.

Йтиметься про консольне введення-виведення. Я маю на увазі організацію обміну інформацією між мікроконтролером і термінальною програмою. Остання є в будь-якій версії Windows і називаєтьсяHyper Terminal або якось схоже, для більшості реальних завдань цього більш ніж достатньо. Підключення традиційно здійснюється через СОМ-порт, причому абсолютно байдуже, як саме він реалізований: чи це буде апаратний RS-232 порт материнської плати, шнур-перехідник USB-RS232 або мікросхема FTDI у зв'язці з мікроконтролером.

Основна проблема бачиться саме у програмі для мікроконтролера. Шанувальники CVAVR, кілька разів клікнувши мишкою, за допомогою Wizard-а отримують заготовку програми, в якій функціїsprintf іscanf вже працюють через USART . Я доведу, що при використанніWinAVR аналогічний результат буде досягатись нітрохи не складніше.

Отже, завантажуємо архів, в якому я приготував три файли. Ці файли ви повинні будете скопіювати в папку вашого проекту, хоча файлavr_helper.h я рекомендував би розмістити в папці з «системними» заголовниками (у папкуavr\include\ всередині папки, куди встановленийWinAVR ), тому що він містить ряд універсальних макросів, які будуть вам корисні частіше, ніж потрібно консольне введення-виведення.

Файлcom_io.c має бути включений до складу проекту для компіляції: якщо ви працюєте зmakefile, то допишіть його в рядок з іншими вихідними джерелами, а якщо користуєтесяAVR Studio > то додайте його до проекту традиційним способом. Користувачам Eclipse взагалі ніяких зусиль докладати не доведеться — усі вихідники з папки проекту автоматично (за умовчанням) додаються до списку компілюваних.

Інший файлcom_io.h повинен бути трохи відредагований, а потім підключений директивою#include у кожному файлі проекту, де буде потрібна робота з консольним введенням-виводом. Редагування цього файлу виконує завдання CVAVR-івського Wizard-а з налаштування необхідних параметрів вводу-виводу:

Власне, це все, що потрібно зробити (. ), щоб у вашому проекті всі функції сімействаprintf виводили через USART в термінал, а всі функції сімействаscanf - вводили дані з консолі ( очевидно, до роботи введення константаONLY_OUT повинна містити нульове значення).

Хочу попередити відразу про деякі моменти, які можуть здивувати програмістів-початківців:

  1. Для підтримкиprintf таscanf автоматично підключаються бібліотеки, які збільшують результуючий код приблизно на 1,5 кілобайта (додаток може бути різним для різних типів мікроконтролерів).
  2. За умовчаннямsprintf таscanf не підтримують роботу з числамиfloat таdouble – якщо необхідно використовувати їх при вводі-виводі, слід підключити примусово бібліотеку підтримки «плаваючої точки» (див. документацію до WinAVR). Підтримка плавучки додасть до вашого проекту ще кілобайт-другий.
  3. Відповідно до стандарту Сі функціїprintf іscanf - це блокуючі функції, в них немаєніякої «вбудованої» буферизації. Це означає буквально наступне: якщо ви задали швидкість обміну 300 бод і вирішили вивести рядок зі 100 символів, цей процес займе більше 3-х секунд. При введенні функціяscanf не поверне керування, доки не будуть введені всі необхідні дані.
  4. За промовчанням зроблено так, що до кожного символу'\n' автоматично додається символ'\r'. Якщо це не потрібно, ви повинні у файліcom_io.c знайти та модифікувати функціюuart_putchar.
  5. У моєму коді не враховано можливість наявності в мікроконтролері більш ніж одного модуляUART /USART. Якщо у МК є два або більше таких модулів, вам доведеться підкоригувати макросіINIT(7) у файліcom_io.c, змінивши найменування регістрів на потрібні, наприклад,UCSRA замінитиUCSR0A абоUCSR1A залежно від номера використовуваногоUSART.

Сподіваюся, тепер всі насправді переконалися, що необхідність у будь-яких автоматичних генераторах вихідних джерел не така вже й велика. На відміну від «бібліотек» CVAVR вихідний код модуля, що розглядається, повністю відкритий і доступний для правки, тому нескладно модифікувати його під будь-які ваші потреби, наприклад, реалізувати висновок в один модульUSART, а введення - в інший.

Окрема примітка для любителів все тестувати у протеусі. З версії в версію протеус тягне одну й ту саму помилку у своєму симуляторі AVR: при виконанні апаратного скидання він не встановлює регістриUART /USART у стан, що наказується датаситом. Тому у файліcom_io.c у макросіINIT(7) ви можете бачити як би «зайві» оператори, що задають початкові значення регістрам — без цього симуляція в протеусі не працюватиме, хоча « взалізі» все добре і без цих операторів. Якщо пара зайвих байт у вашому коді не є вирішальною, рекомендую не змінювати в коді нічого для «сумісності з протеусом».

На закінчення статті пропоную невеликий приклад, знаменитий хелловорд:

printf("\nI like WinAVR!\n");

І ось спробуйте тепер сказати, що консольне введення-виведення у WinAVR – це складно!