新闻中心

EEPW首页>嵌入式系统>设计应用> 【IAR学习】学习笔记

【IAR学习】学习笔记

作者: 时间:2016-11-25 来源:网络 收藏

如果你在C代码的头文件里包含stdbool.h, bool数据类型也可以使用在C语言里。也可以使用布尔值 false和 true。不过是占用8位1个字节。

#i nclude
#i nclude
bool y=0;//定义位变量
void main(void)
{
y=!y;//取反位变量
PORTB_Bit3=y;//传递位变量
}

IAR for AVR 学习笔记(4)--Flash操作

FLASH常用类型的具体操作方法

4.1.FLASH 区域数据存储。

用关键字 __flash 控制来存放, __ flash 关键字写在数据类型前后效果一样
__flash unsigned char a;//定义一个变量存放在flash空间
unsigned char __flash a;//效果同上
__flash unsigned char p[];//定义一个数组存放在flash空间
对于flash空间的变量的读操作同SRAM数据空间的操作方法一样,编译器会自动用
LPM,ELPM 指令来操作。

例:

#i nclude
__flash unsigned char p[];
__flash unsigned char a;
void main(void)
{PORTB=p[1];// 读flash 数组变量的操作
PORTB=a;// 读flash 变量的操作
}

由于在正常的程序中,flash 空间是只读的,所以没有赋值的变量是没有意义的。定义常数在flash 空间,只要给变量赋与初值就可以了。由于常数在flash空间的地址是随机分配的,读取变量才可以读取到常数值。

10

IAR-AVR –C 编译器简要指南

__flash unsigned char a=9;//定义一个常数存放在EEPROM空间。
__flash unsigned char p[]={1,2,3,4,5,6,7,8};
//定义一个组常数存放在flash 空间。

例:

#i nclude
__flash unsigned char p[]={1,2,3,4,5,6,7,8};
__flash unsigned char a=9;
void main(void)
{
PORTB=a;//读取flash 空间值9
PORTC=p[0]; //读取flash 空间值
}

4.1.2flash 空间绝对地址定位:

__flash unsigned char a @ 0x8;//定义变量存放在flash 空间0X08单元__flash unsigned char p[] @ 0x22//定义数组存放在flash 空间,开始地址为0X22单元
__flash unsigned char a @ 0x08=9;//定义常数存放在flash 空间0X08单元
__flash unsigned char p[] @ 0x22={1,2,3,4,5,6,7,8};
//定义一个组常数存放在EEPROM空间开始地址为0X22单元

由于常数在flash 空间的地址是已经分配的,读取flash 空间值可以用变量和地址。

4.2.与 __flash 有关的指针操作。 __flash 关键字控制指针的存放和类型。

4.2.1指向flash 空间的指针flash 指针(控制类型属性)

unsigned char __flash * p;//定义指向flash 空间地址的指针,8位。
unsigned int __flash * p;//定义个指向flash 空间地址的指针,16位。
unsigned int __farflash * p;//定义指向flash 空间地址的指针,24位。
unsigned int __hugeflash * p;//定义指向flash 空间地址的指针,24位。
unsigned char __flash * p;//定义一个指向flash 空间地址的指针,指针本身存放在SARM中。P的值代表flash 空间的某一地址。*p表示flash 空间该地址单元存放的内容。例:假定p=10,表示flash空间地址10单元,而flash M空间10单元的内容就用*p来读取。

例:

#i nclude
char __flash t @ 0x10 ;
char __flash *p ;
void main(void)
{
PORTB=*p;//读取flash 空间10单元的值
PORTB=*(p+3);//读取flash 空间0x13单元的值
}

4.2.2.存储于flash 空间的指针数据指针

就象存储与flash 空间的数据一样控制存储属性

__flash unsigned char * p; //定义指向SARMM空间地址的指针,指针本身存放在flash 中。

4.3.控制数据和指针存放的__flash 定义必须是全局变量,控制类型属性(好像只有指针)可以是局部变量。

#i nclude
__flash unsigned char p;//控制存放
void main(void)
{
unsigned char __flash* t;//控制属性
PORTB=p;
PORTB=*t;
}

4.4. __root 关键字保证没有使用的函数或者变量也能够包含在目标代码中.

定义存放在__flash 空间的数据在程序编译时会自动生成代码嵌入到flash代码中,对于程序没有使用也要求编译的数据(比如可以在代码中嵌入你的版本号,时间等)必须加关键字__root 限制。

例:

#i nclude
__root __flash unsigned char p @ 0x10 =0x56;
void main(void)
{}

程序没有使用P变量,编译也会生成该代码。

:020000020000FC
:1000000016C018951895189518951895189518955F
:10001000569518951895189518951895189518953A
:10002000189518951895089500008895FECF0FE94A
:100030000DBF00E00EBFC0E8D0E003D0F4DFF4DF76
:06004000F3CF01E008957A
:0400000300000000F9
:00000001FF

4.5.flash 操作宏函数:在comp_a90.h intrinsics.h头文件里有详细说明。flash 空间具正常情况下有只读性能,对于读flash 数据编译器会自动编译对应的LPM,ELPM指令,但对于flash 空间的自编程写命令SPM就没有对应的C指令了,这里不讲解详细的自编程方法,只是讲解一下对flash 的读写函数。

直接在程序中读取flash 空间地址数据:要包含intrinsics.h头文件
__load_program_memory(const unsigned char __flash *);//64K空间
//从指定flash 空间地址读数据。该函数在intrinsics.h头文件里有详细说明。

在comp_a90.h文件有它的简化书写_LPM(ADDR)。注意汇编指令LPM Rd ,Z中的Z是一个指针。所以用(const unsigned char __flash *)来强制转换为指向flash空间地址指针。故该条宏函数的正确写法应该如下:

__load_program_memory((const unsigned char __flash *)ADDR);

例:

#i nclude
#i nclude
void main(void)
{PORTB=__load_program_memory((const unsigned char __flash *)0x12);
}

该条函数书写不方便,在comp_a90.h文件有简化:

#define _LPM(ADDR) __load_program_memory (ADDR)稍微方便一点。改为
#define _LPM(ADDR) __load_program_memory ((const unsigned char
__flash *)ADDR)就更方便了,直接使用数据就可以了。

例:

#i nclude
#i nclude
#i nclude
void main(void)
{
PORTB=__LPM(0x12);// 从指定flash 空间地址单元0x12中读数据
}
__extended_load_program_memory(const unsigned char __farflash *);
//128K空间_ELPM(ADDR); //128K空间

参照上面的理解修改可以书写更简单。

4.6.自编程函数:

_SPM_GET_LOCKBITS();//读取缩定位
_SPM_GET_FUSEBITS();//读取熔丝位
_SPM_ERASE(Addr);//16位页擦除
_SPM_FILLTEMP(Addr,Word);//16位页缓冲
_SPM_PAGEWRITE(Addr;)//16位页写入
_SPM_24_ERASE(Addr); //24位页擦除
_SPM_24_FILLTEMP(Addr,Data); //24位页缓冲
_SPM_24_PAGEWRITE(Addr) //24位页写入

IAR for AVR 学习笔记(5)--SRAM操作

SARM数据类型的具体操作方法

SARM空间是AVR单片机最重要的部分,所有的操作必须依赖该部分来完成。变量在SARM空间的存储模式有tiny ,small large 三种,也就是对应于__tiny, __near __far三中存储属性。一旦选择为哪种存储模式,对应的数据默认属性也就确定了,但可以采用__tiny, __near __far关键字来更改。

对于程序中的局部变量,编译器会自动处理的,我们也不可能加什么储存属性,但IAR提供了强大的外部变量定义。

5.1.定义变量在工作寄存器

IAR编译器内部使用了部分工作寄存器,留给用户的只有R4-R15供12个寄存器供用户使用,要使用工作寄存器必须在工程选项里打开锁定选项。

例:

定义两个变量使用工作寄存器R14,R15。

#i nclude
__regvar __no_init char g @ 15;
__regvar __no_init char P @ 14;
void main(void)
{
g++;
P++;
}

在工程选项里c/c++ complier>code里打开要使用的寄存器R14-R15。

编译结果就如下,看看是不是直接使用了寄存器做为数据应用

// 4 void main(void)
main:
CFI Block cfiBlock0 Using cfiCommon0
CFI Function main
// 5 { g++;
REQUIRE ?Register_R14_is_global_regvar
REQUIRE ?Register_R15_is_global_regvar
INC R15
// 6 P++; }
INC R14
RET

注意:定义在寄存器里变量不能带有初始值。最好不要使用超过9个寄存器变量,不然可能引起潜在的危险,因为建立库的时候没有锁定任何寄存器。

5.2.定义变量的绝对地址.没有特性的变量是随机分配的,要给变量分配地址必须加以特性修饰注意在定义地址的时候千万不要和片内寄存器地址重合了。



关键词:IAR学习学习笔

评论


技术专区

关闭