Написання програм на C в Code Vision AVR для контролерів без ОЗУ
Маленькі хитрощі при роботі з Code Vision AVR
CV AVR – хороша інтегрована середа для написання програм на мові високого рівня С для мікроконтролерів сімейства AVR, АТ90, ATMEGA, АТХ MEGA. Велике спасибі розробникам за хорошу програму, але є в ній один суттєвий недолік – це відсутність підтримки контролерів без оперативної пам'яті ОЗУ (RAM), а саме ATTINY11, ATTINY12, ATTINY15. Можна спробувати використовувати інші компілятори, але більшість з них такі як ICCTINY, WinAVR також не підтримують С для цих контролерів. Вдаючись до деяких хитрощів, все ж таки можна писати програми на С для цих контролерів. Для цього необхідно, щоб усі змінні були глобальними і розміщувалися в регістрах, останнє досягається шляхом використання модифікатора register при оголошенні змінних.
register insigned int k;
При такому оголошенні змінних середа сама розмістить змінні в регістрах. За замовчуванням вона розмістить їх у регістрах з R16 по R21. Якщо ви хочете використовувати регістри на свій розсуд, то це можна зробити за допомогою директиви препроцесора #pragma regalloc- і вказати самостійно, куди помістити ту чи іншу змінну.
register char ttp @12;
register int tmp @10;
Таким чином компілятор розмістить змінну ttp в регістрі R12, а змінну tmp у регістрах R10, R11, так як змінна типу int займає два байти.
Крок другий, необхідно вимкнути генерацію startup коду, тобто коду, який виконується до початку роботи основної програми. Для цього в властивостях проекту
На вкладці C Compiler потрібно встановити прапорець зовнішнього startup файлу рис.2. Далі з каталогу BIN програми скопіювати файл STARTUP.ASM у каталог проекту і підправити його, видаливши команди очищення пам'яті SRAM, так як її немає у наших контролерах, змінити регістр непрямої адресації та прибрати ініціалізацію глобальних змінних.
;CodeVisionAVR C Compiler ;(C) 1998-2004 Pavel Haiduc, HP InfoTech s.r.l. ;EXAMPLE STARTUP FILE FOR CodeVisionAVR V1.24.1 OR LATER.EQU __CLEAR_START=0X60 ;START ADDRESS OF SRAM AREA TO CLEAR ;SET THIS ADDRESS TO 0X100 FOR THE ;ATmega128 OR ATmega64 CHIPS .EQU __CLEAR_SIZE=256 ;SIZE OF SRAM AREA TO CLEAR IN BYTESCLI ;DISABLE INTERRUPTS CLR R30 OUT EECR,R30 ;DISABLE EEPROM ACCESS ;DISABLE THE WATCHDOG LDI R31,0x18 OUT WDTCR,R31 OUT WDTCR,R30 OUT MCUCR,R30 ;MCUCR=0, NO EXTERNAL SRAM ACCESS ;CLEAR R2-R14 LDI R24,13 LDI R26,2 CLR R27 __CLEAR_REG:ST X+,R30 ; У наших контролерах немає регістра X, тому замінимо його на YST Y+,R30 DEC R24 BRNE __CLEAR_REG;CLEAR SRAM LDI R24,LOW(__CLEAR_SIZE) LDI R25,HIGH(__CLEAR_SIZE) LDI R26,LOW(__CLEAR_START) LDI R27,HIGH(__CLEAR_START) __CLEAR_SRAM: ST X+,R30 SBIW R24,1 BRNE __CLEAR_SRAM ;GLOBAL VARIABLES INITIALIZATION LDI R30,LOW(__GLOBAL_INI_TBL*2) LDI R31,HIGH(__GLOBAL_INI_TBL*2) __GLOBAL_INI_NEXT: LPM ADIW R30,1 MOV R24,R0 LPM ADIW R30,1 MOV R25,R0 SBIW R24,0 BREQ __GLOBAL_INI_END LPM ADIW R30,1 MOV R26,R0 LPM ADIW R30,1 MOV R27,R0 LPM ADIW R30,1 MOV R1,R0 LPM ADIW R30,1 MOV R22,R30 MOV R23,R31 MOV R31,R0 MOV R30,R1 __GLOBAL_INI_LOOP: LPM ADIW R30,1 ST X+,R0 SBIW R24,1 BRNE __GLOBAL_INI_LOOP MOV R30,R22 MOV R31,R23 RJMP __GLOBAL_INI_NEXT __GLOBAL_INI_END:
Червоним позначено все, що потрібно прибрати.
Крок третій, необхідно підключити заголовний файл. Оскільки в каталозі INC програми відсутні заголовні файли для наших контролерів, то ми можемо використовувати файл TINY13.h, так як, наприклад, tiny13 і tiny 15 мають практично однаковий склад регістрів, розташованих за одними і тими ж адресами, але обов'язково з оглядкою на datasheet використовуваного контролера. У доданому прикладі два регістри все ж відрізнялися, тому для наглядності зробив додаткове визначення.
При написанні програм на С для контролерів без оперативної пам'яті необхідно пам'ятати, що ці мікросхеми мають трирівневий апаратний стек, в якому зберігаються адреси повернення з функцій, так, що не слід захоплюватися вкладеними функціями, щоб уникнути переповнення стека.
Якщо передбачається використовувати в своїй програмі переривання, то обов'язково необхідно використовувати директиву препроцесора #pragma savereg-, яка наказує компілятору не зберігати автоматично регістри в пам'ять при вході в процедуру обробки переривання.
#pragma savereg-
#pragma regalloc-
register char ttp @12;
Далі, після написання програми і її компіляції, необхідно підправити вихідний asm файл, який буде знаходитись у робочому каталозі проекту. У ньому компілятор генерує команди ініціалізації стека, яких немає у наших контролерах. Прибрати потрібно всього 4 рядки, які знаходяться безпосередньо перед початком основної програми:
.CSEG .ORG 0 .INCLUDE "1.vec" .INCLUDE "1.inc" __RESET: .INCLUDE "STARTUP.ASM";STACK POINTER INITIALIZATION LDI R30,LOW(0x9F) OUT SPL,R30 ;DATA STACK POINTER INITIALIZATION LDI R28,LOW(0x70) LDI R29,HIGH(0x70)RJMP _main .ESEG .ORG 0 .DSEG .ORG 0x70 ; 1 #include; 2 ; 3 register unsigned char i; ; 4 void main(void)
Після цього можна компілювати вихідний asm файл. Робити це потрібно тому, що ми його трохи підправили і той hex, що згенерувала програма, нам вже не підійде. Зробити це можна просто, в каталозі BIN програми знаходиться компілятор avrasm2.exe, його можна скопіювати в каталог проекту і виконати команду:
avrasm2.exe –fI –o myfile.hex myfile.asm
Проект часто доводиться перекомпільовувати, тому, щоб не писати в командному рядку багато разів одне й те саме, можна створити файл з розширенням bat (myfile.bat) і записати в нього команду, приведену нижче, тепер для перекомпіляції достатньо його запустити, і в підсумку ви отримаєте готовий до використання hex файл.
Тепер про програмування контролера. Спеціально для вас я зібрав маленьке демонстраційне пристрій на ATTINY15, що складається з контролера, двох резисторів і світлодіода, і запрограмував його.
Текст програми на мові С, написаний в CVAVR 1.24.8d
/*********************************************/ /* Demo project ATTINY15 */ /* Cade Vision AVR 1.24.8d */ /* by Panda_Y2K */ /* 2012 */ /*********************************************/ #includesfrb OCR1A=0x2e; sfrb TCCR1=0x30; register unsigned char i,j; void main(void) { GIMSK = 0; TIMSK0 = 0x00; TCCR0B = 0x00; PORTB = 0; //Clear PORTB DDRB = 0x02; //PORTB.1 out // CTC = 0, PWM1 = 1, COM1A1 = 1, COM1A0 = 0, CS13 = 0, CS12 = 1, CS11 = 1, CS10 = 1 // CK/4 TCCR1 = 0x67; while (1) { for (i=255; i>0; i--) {OCR1A = i; for (j=255; j>0; j--); }; }; } //end of main
CVAVR шити контролер вперто не хотів, але SinaProg цілком справився з завданням.
Програматор використовувався USBTiny
Відео роботи пристрою можна подивитися за посиланням.
Скачати вихідний код
Автор: Panda_Y2K