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

Йтиметься про консольне введення-виведення. Я маю на увазі організацію обміну інформацією між мікроконтролером і термінальною програмою. Остання є в будь-якій версії 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 повинна містити нульове значення).
Хочу попередити відразу про деякі моменти, які можуть здивувати програмістів-початківців:
- Для підтримкиprintf таscanf автоматично підключаються бібліотеки, які збільшують результуючий код приблизно на 1,5 кілобайта (додаток може бути різним для різних типів мікроконтролерів).
- За умовчаннямsprintf таscanf не підтримують роботу з числамиfloat таdouble – якщо необхідно використовувати їх при вводі-виводі, слід підключити примусово бібліотеку підтримки «плаваючої точки» (див. документацію до WinAVR). Підтримка плавучки додасть до вашого проекту ще кілобайт-другий.
- Відповідно до стандарту Сі функціїprintf іscanf - це блокуючі функції, в них немаєніякої «вбудованої» буферизації. Це означає буквально наступне: якщо ви задали швидкість обміну 300 бод і вирішили вивести рядок зі 100 символів, цей процес займе більше 3-х секунд. При введенні функціяscanf не поверне керування, доки не будуть введені всі необхідні дані.
- За промовчанням зроблено так, що до кожного символу'\n' автоматично додається символ'\r'. Якщо це не потрібно, ви повинні у файліcom_io.c знайти та модифікувати функціюuart_putchar.
- У моєму коді не враховано можливість наявності в мікроконтролері більш ніж одного модуля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 – це складно!