ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.06.2025

Просмотров: 2211

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

CodeVisionAVR

3.7 Variables

Program variables can be global (accessible to all the functions in the program) or local (accessible only inside the function they are declared).

If not specifically initialized, the global variables are automatically set to 0 at program startup. The local variables are not automatically initialized on function call.

The syntax is:

[<storage modifier>] <type definition> <identifier>;

Example:

/* Global variables declaration */ char a;

int b;

/* and initialization */ long c=1111111;

void main(void) {

/* Local variables declaration */ char d;

int e;

/* and initialization */ long f=22222222;

}

Variables can be grouped in arrays, which can have up to 8 dimensions. The first element of the array has always the index 0.

If not specifically initialized, the elements of global variable arrays are automatically set to 0 at program startup.

Example:

/* All the elements of the array will be 0 */ int global_array1[32];

/* Array is automatically initialized */ int global_array2[]={1,2,3};

int global_array3[4]={1,2,3,4};

char global_array4[]=”This is a string”;

/* Only the first 3 elements of the array are initialized, the rest 29 will be 0 */

int global_array5[32]={1,2,3};

/* Multidimensional array */

int multidim_array[2][3]={{1,2,3},{4,5,6}};

void main(void) {

/* local array declaration */ int local_array1[10];

/* local array declaration and initialization */ int local_array2[3]={11,22,33};

char local_array3[7]="Hello";

}

© 1998-2007 HP InfoTech S.R.L.

Page 75

CodeVisionAVR

Local variables that must conserve their values during different calls to a function must be declared as static. Example:

int alfa(void) {

/* declare and initialize the static variable */ static int n=1;

return n++;

}

void main(void) { int i;

/* the function will return the value 1 */ i=alfa();

/* the function will return the value 2 */ i=alfa();

}

If not specifically initialized, static variables are automatically set to 0 at program startup.

Variables that are declared in other files must be preceded by the extern keyword. Example:

extern int xyz;

/* now include the file which contains the variable xyz definition */

#include <file_xyz.h>

To instruct the compiler to allocate a variable to registers, the register modifier must be used. Example:

register int abc;

The compiler may automatically allocate a variable to registers, even if this modifier is not used.

The volatile modifier must be used in order to prevent a variable to be allocated to registers and to warn the compiler that it may be subject to outside change during evaluation.

Example:

volatile int abc;

All the global variables, not allocated to registers, are stored in the Global Variables area of SRAM. All the local variables, not allocated to registers, are stored in dynamically allocated space in the Data Stack area of SRAM.

© 1998-2007 HP InfoTech S.R.L.

Page 76


CodeVisionAVR

3.7.1 Specifying the SRAM Storage Address for Global Variables

Global variables can be stored at specific SRAM locations at design-time using the @ operator. Example:

/* the integer variable "a" is stored in SRAM at address 80h */

int a @0x80;

/* the structure "alfa" is stored in SRAM at address 90h */

struct x {

int a; char c;

}alfa @0x90;

3.7.2Bit Variables

The global bit variables located in the GPIOR register(s) and R2 to R14 memory space. These variables are declared using the bit keyword.

The syntax is:

bit <identifier>;

Example:

/* declaration and initialization for an ATtiny2313 chip which has GPIOR0, GPIOR1 and GPIOR2 registers */

bit alfa=1; /* bit0 of GPIOR0 */ bit beta; /* bit1 of GPIOR0 */

void main(void)

{

if (alfa) beta=!beta;

/* ........

*/

}

Memory allocation for the global bit variables is done, in the order of declaration, starting with bit 0 of GPIOR0, then bit 1 of GPIOR0 and so on, in ascending order.

After all the GPIOR registers are allocated, further bit variables are allocated in R2 up to R14. If the chip does not have GPIOR registers, the allocation begins directly from register R2.

The size of the global bit variables allocated to the program can be specified in the

Project|Configure|C Compiler|Code Generation|Bit Variables Size list box.

This size should be as low as possible, in order to free registers for allocation to other global variables. If not specifically initialized, the global bit variables are automatically set to 0 at program startup.

© 1998-2007 HP InfoTech S.R.L.

Page 77

CodeVisionAVR

The compiler allows also to declare up to 8 local bit variables which will be allocated in register R15. Example:

void main(void)

{

bit alfa; /* bit 0 of R15 */ bit beta; /* bit 1 of R15 */ /* ........ */

}

In expression evaluation bit variables are automatically promoted to unsigned char.

© 1998-2007 HP InfoTech S.R.L.

Page 78


CodeVisionAVR

3.7.3 Allocation of Variables to Registers

In order to fully take advantage of the AVR architecture and instruction set, the compiler allocates some of the program variables to chip registers.

The registers from R2 up to R14 can be allocated for global bit variables. The register R15 can be allocated to local bit variables.

You may specify how many registers in the R2 to R14 range are allocated for global bit variables using the Project|Configure|C Compiler|Code Generation|Bit Variables Size list box. This value must be as low as required by the program.

If the Project|Configure|C Compiler|Code Generation|Automatic Register Allocation option is checked or the #pragma regalloc+ compiler directive is used, the rest of registers in the R2 to R14 range, that aren’t used for global bit variables, are allocated to char and int global variables and global pointers.

If the Project|Configure|C Compiler|Code Generation|Smart Register Allocation option is checked, the allocation of registers R2 to R14 (not used for bit variables) is performed in such a way that 16bit variables will be preferably located in even register pairs, thus favouring the usage of the enhanced core MOVW instruction for their access.

Otherwise the allocation is performed in order of variable declaration until the R14 register is allocated.

If the automatic register allocation is disabled, you can use the register keyword to specify which global variable to be allocated to registers.

Example:

/* disable automatic register allocation */ #pragma regalloc-

/* allocate the variable ‘alfa’ to a register */ register int alfa;

/* allocate the variable ‘beta’ to the register pair R10, R11 */ register int beta @10;

Local char, int and pointer local variables are allocated to registers R16 to R21.

If the Project|Configure|C Compiler|Code Generation|Smart Register Allocation option is checked, the allocation of these registers for local variables is performed in such a way that 16bit variables will be preferably located in even register pairs, thus favouring the usage of the enhanced core MOVW instruction for their access.

Otherwise the local variables are automatically allocated to registers in the order of declaration.

The Project|Configure|C Compiler|Code Generation|Smart Register Allocation option should be disabled if the program was developed using CodeVisionAVR prior to V1.25.3 and it contains inline assembly code that accesses the variables located in registers R2 to R14 and R16 to R21.

© 1998-2007 HP InfoTech S.R.L.

Page 79

CodeVisionAVR

3.7.4 Structures

Structures are user-defined collections of named members.

The structure members can be any of the supported data types, arrays of these data types or pointers to them.

Structures are defined using the struct reserved keyword. The syntax is:

[<storage modifier>] struct [<structure tag-name>] { [<type> <variable-name>[,<variable-name>, ...]];

[<type> [<bitfield-id>]:<width>[,[<bitfield-id>]:<width>, ...]];

...

} [<structure variables>];

Example:

/* Global structure located in SRAM */ struct ram_structure {

char a,b; int c;

char d[30],e[10]; char *pp;

} sr;

/* Global constant structure located in FLASH */ flash struct flash_structure {

int a;

char b[30], c[10]; } sf;

/* Global structure located in EEPROM */ eeprom struct eeprom_structure {

char a; int b; char c[15]; } se;

void main(void) {

/* Local structure */ struct local_structure {

char a; int b; long c; } sl;

/* .............

*/

}

The space allocated to the structure in memory is equal to sum of the sizes of all the members.

There are some restrictions that apply to the structures stored in FLASH and EEPROM.

Due to the fact that pointers must be always located in SRAM, they can't be used in these structures.

Because with the Atmel AVRASM32 Assembler single bytes defined with .DB in FLASH occupy in reality 2 bytes, the CodeVisionAVR C compiler will replace the char members of structures stored in FLASH with int.

Also it will extend the size of the char arrays, members of such structures, to an even value.

© 1998-2007 HP InfoTech S.R.L.

Page 80


CodeVisionAVR

Structures can be grouped in unidimensional arrays.

Example how to initialize and access an global structure array stored in EEPROM:

/* Global structure array located in EEPROM */ eeprom struct eeprom_structure {

char a; int b; char c[15];

} se[2]={{'a',25,"Hello"}, {'b',50,"world"}};

void main(void) { char k1,k2,k3,k4; int i1, i2;

/* define a pointer to the structure */ struct eeprom_structure eeprom *ep;

/* direct access to structure members */ k1=se[0].a;

i1=se[0].b;

k2=se[0].c[2];

k3=se[1].a;

i2=se[1].b;

k4=se[1].c[2];

/* same access to structure members using a pointer */

ep=&se; /* initialize the pointer with the structure address */ k1=ep->a;

i1=ep->b; k2=ep->c[2];

++ep; /* increment the pointer */ k3=ep->a;

i2=ep->b; k4=ep->c[2];

}

Because some AVR devices have a small amount of SRAM, in order to keep the size of the Data Stack small, it is recommended not to pass structures as function parameters and use pointers for this purpose.

Example:

struct alpha {

int a,b, c; } s={2,3}; /* define the function */

struct alpha *sum_struct(struct alpha *sp) { /* member c=member a + member b */ sp->c=sp->a + sp->b;

/* return a pointer to the structure */ return sp;

}

void main(void) { int i;

/* s->c=s->a + s->b */ /* i=s->c */ i=sum_struct(&s)->c;

}

© 1998-2007 HP InfoTech S.R.L.

Page 81

CodeVisionAVR

Structure members can be also declared as bit fields, having a width from 1 to 32. Bit fields are allocated in the order of declaration starting from the least significant bit. Example:

/* this structure will occupy 1 byte in SRAM

as the bit field data type is unsigned char */ struct alpha1 {

unsigned char a:1; /* bit 0 */ unsigned char b:4; /* bits 1..4 */ unsigned char c:3; /* bits 5..7 */ };

/* this structure will occupy 2 bytes in SRAM as the bit field data type is unsigned int */

struct alpha2 {

unsigned int a:2; /* bits 0..1 */ unsigned int b:8; /* bits 2..9 */ unsigned int c:4; /* bits 10..13 */

/* bits 14..15 are not used */

};

/* this structure will occupy 4 bytes in SRAM

as the bit field data type is unsigned long */ struct alpha3 {

unsigned long a:10; /* bits 0..9 */ unsigned long b:8; /* bits 10..17 */ unsigned long c:6; /* bits 18..23 */

/* bits 24..31 are not used */

};

© 1998-2007 HP InfoTech S.R.L.

Page 82


CodeVisionAVR

3.7.5 Unions

Unions are user-defined collections of named members that share the same memory space.

The union members can be any of the supported data types, arrays of these data types or pointers to them.

Unions are defined using the union reserved keyword. The syntax is:

[<storage modifier>] union [<union tag-name>] { [<type> <variable-name>[,<variable-name>, ...]];

[<type> <bitfield-id>:<width>[,<bitfield-id>:<width>, ...]];

...

} [<union variables>];

Unions are always stored in SRAM.

The space allocated to the union in memory is equal to the size of the largest member. Union members can be accessed in the same way as structure members. Example:

/* union declaration */ union alpha {

unsigned char lsb; unsigned int word; } data;

void main(void) { unsigned char k;

/* define a pointer to the union */ union alpha *dp;

/* direct access to union members */ data.word=0x1234;

k=data.lsb; /* get the LSB of 0x1234 */

/* same access to union members using a pointer */

dp=&data; /* initialize the pointer with the union address */ dp->word=0x1234;

k=dp->lsb; /* get the LSB of 0x1234 */

}

Because some AVR devices have a small amount of SRAM, in order to keep the size of the Data Stack small, it is recommended not to pass unions as function parameters and use pointers for this purpose.

Example:

#include <stdio.h> /* printf */ union alpha {

unsigned char lsb; unsigned int word; } data;

/* define the function */

unsigned char low(union alpha *up) { /* return the LSB of word */

return up->lsb;

}

void main(void) { data.word=0x1234;

printf("the LSB of %x is %2x",data.word,low(&data));

}

© 1998-2007 HP InfoTech S.R.L. Page 83

CodeVisionAVR

Union members can be also declared as bit fields, having a width from 1 to 32.

Bit fields are allocated in the order of declaration starting from the least significant bit. Example:

/* this union will occupy 1 byte in SRAM

as the bit field data type is unsigned char */ union alpha1 {

unsigned char a:1; /* bit 0 */ unsigned char b:4; /* bits 0..3 */ unsigned char c:3; /* bits 0..2 */ };

/* this union will occupy 2 bytes in SRAM

as the bit field data type is unsigned int */ union alpha2 {

unsigned int a:2; /* bits 0..1 */ unsigned int b:8; /* bits 0..7 */ unsigned int c:4; /* bits 0..3 */

/* bits 8..15 are not used */

};

/* this union will occupy 4 bytes in SRAM

as the bit field data type is unsigned long */ union alpha3 {

unsigned long a:10; /* bits 0..9 */ unsigned long b:8; /* bits 0..7 */ unsigned long c:6; /* bits 0..5 */

/* bits 10..31 are not used */

};

© 1998-2007 HP InfoTech S.R.L.

Page 84

CodeVisionAVR

3.7.6 Enumerations

The enumeration data type can be used in order to provide mnemonic identifiers for a set of char or int values.

The enum keyword is used for this purpose. The syntax is:

[<storage modifier>] enum [<enum tag-name>] { [<constant-name[[=constant-initializer], constant-name, ...]>]} [<enum variables>];

Example:

/* The enumeration constants will be initialized as follows: sunday=0 , monday=1 , tuesday=2 ,..., saturday=6 */

enum days {

sunday, monday, tuesday, wednesday, thursday, friday, saturday} days_of_week;

/* The enumeration constants will be initialized as follows: january=1 , february=2 , march=3 ,..., december=12 */

enum months {

january=1, february, march, april, may, june,

july, august, september, october, november, december} months_of_year;

void main {

/* the variable days_of_week is initialized with the integer value 6 */

days_of_week=saturday;

}

Enumerations can be stored in SRAM or EEPROM.

To specify the storage in EEPROM, the eeprom keyword must be used.

Example:

eeprom enum days {

sunday, monday, tuesday, wednesday, thursday, friday, saturday} days_of_week;

It is recommended to treat enumerations as having 8 bit char data type, by checking the 8 bit enums check box in Project|Configure|CompilerCode Generation. This will improve the size and execution speed of the compiled program.

© 1998-2007 HP InfoTech S.R.L.

Page 85