Маленькие хитрости при работе с 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 кода, то есть кода который выполняется до начала работы основной программы. Для этого в свойствах проекта
На вкладке 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 ; В наших контроллерах нет регистра Х, поэтому заменим его на 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 используемого контроллера. В прилагаемом примере два регистра все же отличались, по этому для наглядности сделал дополнительное определение.
При написании программ на С для контроллеров без оперативной памяти необходимо помнить, что эти микросхемы имеют 3-х уровневый аппаратный стек, в котором хранятся адреса возврата из функций, так, что не стоит увлекаться вложенными функциями, во избежание переполнения стека.
Если предполагается использовать в своей программе прерывания, то обязательно необходимо использовать директиву препроцессора #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 состоящее из контроллера, 2-х резисторов и светодиода, и запрограммировал его.
Текст программы на языке С написанный в 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 вполне справился с задачей.
Программатор использовался USBTiny
Видео работы устройства можно посмотреть по ссылке.
Скачать исходник
Автор: Panda_Y2K