У цій статті вирішив записувати все цікаве, яке вдалося накопати при роботі в середовищі програмування IAR Embedded Workbench for AVR (і для програмування з використанням AVR GCC).
void main (void)
while (1)
//. тут потім потрібно додати код програми
>
>
2. Додайте в початок main.c заголовки, який описує регістри вашого процесора:
3. Додайте в заголовки в початок модуля коду:
#define false 0
#define true 1
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
4. Після додавання файлу iotiny24.h (ім'я заголовки визначається типом обраного процесора, тут в якості прикладу взято процесор ATTINY24) можна зручно управляти портами. Використовується також прапорець ENABLE_BIT_DEFINITIONS. що включає визначення бітів. Після включення заголовки iotiny24.h і прапорця ENABLE_BIT_DEFINITIONS можливі такі операції, як, наприклад:
#define ENABLE_BIT_DEFINITIONS
#include
.
// так ми переключили розряди 4, 5 і 6 порту A в режим виходу.
DDRA_DDA6 = 1;
DDRA_DDA5 = 1;
DDRA_DDA4 = 1;
Дуже ефективні оператори типу регістр = (1 <<имя_бита), например:
// відключаємо цифровий буфер на ніжках 0, 4 і 5 порту A 5. Приклад програми, миготливою червоним світлодіодом (світлодіоди _RED, _GRN і _YEL підключені до + 5V харчування через струмообмежуючі резистори): #include void main (void) // перемикаємо світлодіодні порти в режим виходу // вимикаємо світлодіоди #include HKEY_CURRENT_USER \ Software \ IAR Systems \ IAR Embedded Workbench IDE \ Recent Workspaces \ Почистити його можна тільки за допомогою regedit. Доцільно ще додати такі комбінації кнопок (в меню Debug): 8. Найпростіший спосіб увійти в режим Power Down на ATtiny45: Після цього вийти з режиму Sleep можна тільки по перериванню Watchdog, переривання INT0 або переривання Pin Change, USI Start condition і по скиданню. 9. Те ж саме, але з дозволом виходу з Power Down по перериванню PCI - Pin Change Interrupt. У прикладі використовується ніжка 7 ATtiny45, на яку повішена кнопка (див. Схему макетної плати): // SE = 1 - Sleep Enable 10. Як написати обробник переривання. наприклад, для вектора PCINT0: // директиві #pragma vector = потрібно вказати номер вектора Тепер, якщо у нас налагоджена переривання Pin Change Interrupt, як було зазначено в попередньому раді, то буде замість заглушки RETI викликатися цей код (__no_operation ();). #define WDT128ms 0x03 #pragma vector = WDT_vect Тепер скидання не буде, просто процесор буде кожні 128 мс прокидатися (якщо була викликана команда __sleep ();). 12. Команда SLEEP виконується дуже швидко, так що іноді не встигають застосуватися результати дії попередньої команди: Якби не було чотирьох команд NOP, то порт B не встиг би переключитися на вхід. У мене, наприклад, продовжував горіти світлодіод, підключений до ніжки PB2 (після SLEEP він продовжував працювати як вихід). Кількість неодружених операцій перед командою SLEEP доводиться підбирати експериментально (іноді для цього краще використовувати цикли). 13. Мінлива float займає 4 байта. 14. Щоб змінна зберігалася в EEPROM і була доступна при перезавантаженні і перепідключенні харчування, потрібно вказати атрибут пам'яті __eeprom і ключове слово __no_init (без __no_init змінна при старті обнулятиметься), наприклад: __no_init __eeprom float fVar; uchar Adr; 15. Рано радіти і розслаблятися, користуючись принадами програмування на Сі - пам'ять відлітає в трубу зовсім непомітно, особливо якщо використовувати типи float, рядки (це відразу включає в код бібліотечні функції) - за зручності треба платити. Напевно, найбільше незручність архітектури AVR - витрата як мінімум відразу 2 байт на одну команду асемблера. 17. Для генерування випадкового цілого числа в діапазоні 0..32767 (або від 0 до константи RAND_MAX) існує наявна в бібліотеці CLIB або DLIB функція rand (). Щоб її можна було використовувати, треба додати в main.c включається файл stdlib.h. Щоб генерувати випадкове число в будь-якому потрібному діапазоні, потрібно скористатися операцією ділення по модулю (%). Наприклад, так генерується випадкове бінарне число (true або false. Т. Е. Випадкове число від 0 до 1): А так генерітся число від 0 до 9: 18. Щоб роздрукувати знак відсотка% за допомогою printf (або sprintf), потрібно його повторити двічі: printf ( "Це знак відсотка: %%"); 19. Деякі глобальні або статичні змінні можна помістити прямо в регістри процесора R4-R15, що істотно підвищить швидкість роботи зі змінними. Для цього потрібно при декларуванні змінної використовувати розширене ключове слово __regvar. а також використовувати для компілятора опцію --lock_regs. Приклад декларування реєстрової змінної (буде використовуватися реєстрова пара R15: R14): __regvar __no_init int counter @ 14; Обмеження: Максимальний розмір об'єкта, який можна виділити в регістрах за допомогою директиви __regvar, дорівнює 4 байтам. Неможливо використовувати покажчики на змінну, виділену за допомогою директиви __regvar. Крім того, не можна при декларуванні задати об'єкту початкову величину. Крім того, якщо Ви використовуєте __regvar, то блокуєте таким чином регістри під змінну, і використовувані бібліотеки теж повинні бути перекомпіліровать з тим же набором заблокованих регістрів. Тому такі збочення краще використовувати в крайніх випадках - напевно, найкращою альтернативою буде написати окремий модуль на асемблері. Все сказане в цій раді можна знайти в довіднику по компілятору IAR, файл c: \ Program Files \ IAR AVR Embedded Workbench 4.0 \ avr \ doc \ EWAVR_CompilerReference.pdf. Див. __regvar, --lock_regs, --memory_model. 20. Проблема з Build Actions -> Post-build command line: неможливо запустити необхідні утиліти після компіляції. Зазвичай проблема пов'язана зі шляхами запуску програм. В цьому випадку вікні View -> Messages -> Build після компіляції з'являється запис "Total number of errors: 1" (хоча помилок синтаксису при компіляції не було), і потрібні дії, зазначені в командному рядку запуску Post-build command line не відбуваються. Труднощі виявлення і виправлення таких помилок в тому, що немає ніякої інформації про причини проблеми. Перше, що потрібно перевірити - шлях до місця знаходження виконуваної утиліти. Вона повинна бути запущена по повному прямо вказаним шляхом, або шлях запуску повинен бути прописаний в змінної оточення% Path%. Якщо виконується програма знаходиться в межах папок проекту, то використовуйте вбудований в IAR макрос $ PROJ_DIR $, який вказує на місце розташування файлів налаштувань проекту * .ewp і * .eww. Профіт використання $ PROJ_DIR $ в тому, що вона дозволяє відв'язатися від абсолютних шляхів, і можна спокійно копіювати або переносити проект в будь-яку папку на диску, не втрачаючи його працездатності. Друге, що потрібно перевірити - чи бачить запускається ті файли, які треба обробити. Якщо програма очікує побачити вхідні файли в своєму поточному каталозі, то використовуйте командний файл для запуску утиліти, і всередині командного файлу використовуйте команду cd для переходу в каталог утиліти. Поточний шлях проекту передавайте через опцію командного файлу. Приклад грамотно настроєної рядки Post-build command line: Приклад файлу post_build_pu.bat: 21. Як обчислити кількість елементів в масиві структур або масиві елементів якогось певного типу? Підійде макрос countof: Як вирішити проблему, не вдаючись до вимикання налагодження (опції -O0 і т. П.)? Іноді вимкнути налагодження не представляється можливим. ИМХО найпростіший спосіб - привласнити змінної атрибут volatile, тоді компілятор буде її оптимізувати, і виділить для цієї змінної окрему комірку пам'яті. Тепер змінні ss, mm і hh будуть легко доступні при покрокової налагодження. Ця рада добре підходить для більшості компіляторів, як IAR, так і GCC. Також для AVR GCC (починаючи з версії 4.4) можна відключити оптимізацію для блоку коду за допомогою директиви pragma: Для функції можна відключити оптимізацію додаванням атрибуту __attribute __ ((optimize ( "O0"))). наприклад так:
DIDR0 = (1<
// Рядок #include
// функція __delay_cycles.
#include
#define _RED PORTA_PORTA6
#define _GRN PORTA_PORTA5
#define _YEL PORTA_PORTA4
#define delay 1000000
DDRA_DDA6 = 1;
DDRA_DDA5 = 1;
DDRA_DDA4 = 1;
_RED = 1;
_YEL = 1;
_GRN = 1;
while (true)
_RED = 0; // на виході 0, червоний LED горить
__delay_cycles (delay / 10);
_RED = 1; // на виході 1, червоний LED загасили
__delay_cycles (delay - (a / 10));
>
>
#define _KEY PINA_PINA6
.
if (_KEY == false)
// кнопку натиснуто!
>
#define _KEY PINB_PINB2
#define YEL PB2
#define _YEL PORTB_PORTB2
.
if (_KEY == false)
// кнопку натиснуто!
.
>
C - Program Files-IAR AVR Embedded Workbench 4.0-common-bin-IarIdePm.exe.
Reset Ctrl + R
Stop Debugging Alt + D
Break Esc
// SM1 = 1 і SM0 = 0 - після команди __sleep () включиться режим
// Power Down
MCUCR = (1<
GIMSK = 1<
// (KEY == PCINT2 == PB2)
PCMSK = 1<
SREG_I = 1;
__sleep ();
// далі йде код, який буде виконуватися тільки після
// натискання на кнопку.
.
// переривання, список векторів заданий в файлі iotiny45.h
#pragma vector = PCINT0_vect
// ім'я PCINT0_routine взято довільно
__interrupt void PCINT0_routine (void)
__no_operation ();
>
WDTCR = (1<
SREG_I = 1;
__interrupt void WDT_routine (void)
__no_operation ();
WDTCR_WDTIE = 1;
>
Adr = (uchar)&fVar;Схожі статті