Написання програм на C в Code Vision AVR для контролерів без ОЗУ

Маленькі хитрощі при роботі з Code Vision AVR

CV AVR – хороша інтегрована середа для написання програм на мові високого рівня С для мікроконтролерів сімейства AVR, АТ90, ATMEGA, АТХ MEGA. Велике спасибі розробникам за хорошу програму, але є в ній один суттєвий недолік – це відсутність підтримки контролерів без оперативної пам'яті ОЗУ (RAM), а саме ATTINY11, ATTINY12, ATTINY15. Можна спробувати використовувати інші компілятори, але більшість з них такі як ICCTINY, WinAVR також не підтримують С для цих контролерів. Вдаючись до деяких хитрощів, все ж таки можна писати програми на С для цих контролерів. Для цього необхідно, щоб усі змінні були глобальними і розміщувалися в регістрах, останнє досягається шляхом використання модифікатора register при оголошенні змінних.

register unsigned char i;
register insigned int k;

При такому оголошенні змінних середа сама розмістить змінні в регістрах. За замовчуванням вона розмістить їх у регістрах з R16 по R21. Якщо ви хочете використовувати регістри на свій розсуд, то це можна зробити за допомогою директиви препроцесора #pragma regalloc- і вказати самостійно, куди помістити ту чи іншу змінну.

#pragma regalloc-
register char ttp @12;
register int tmp @10;

Таким чином компілятор розмістить змінну ttp в регістрі R12, а змінну tmp у регістрах R10, R11, так як змінна типу int займає два байти.

Крок другий, необхідно вимкнути генерацію startup коду, тобто коду, який виконується до початку роботи основної програми. Для цього в властивостях проекту

CodeVisionAVR

На вкладці 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 BYTES
CLI ;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, тому замінимо його на Y
ST 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                                               */
/*********************************************/

#include 

sfrb 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 цілком справився з завданням.

Зовнішній вигляд SinaProg

Програматор використовувався USBTiny

Програматор USBTiny

Відео роботи пристрою можна подивитися за посиланням.

Скачати вихідний код

Автор: Panda_Y2K

Top