今日在阅览RF_Example_Code_v1.0中头文件cc430x613x.h时发现了几部分的疑问。
首要来看一下cc430x613x.h 中的3个#define的比如:
#define DEFC(name, address) __no_init volatile unsigned char name @ address;
#define DEFW(name, address) __no_init volatile unsigned short name @ address;
#define DEFCW(name, address) __no_init union
{
struct
{
volatile unsigned char name##_L;
volatile unsigned char name##_H;
};
volatile unsigned short name;
} @ address;
前面的两个#define的用法是相同的。首要我能够发现,在宏界说里边都有一个关键字__no_init。查看了《MSP430 IAR C/EC++ Compiler Reference Guide》内的IAR Language Extension Overview 能够发现,__no_init是IAR扩展语法里边的一个扩展关键字。效果是声明一个non-volatile类型的内存地址(Support non-valotile memory)。
所以处理了__no_init的问题。
再者对@这个字符存在必定的疑问,所以上网查了查资料。尽管关于@这个字符的用法仍是不是很清晰,可是能够清晰的是:
#define DEFC(name, address) __no_init volatile unsigned char name @ address;
#define DEFC(name, address) sfrb name = address;
这两种界说是等价的,可是后者是根据汇编嵌入式编程的情况下才建立。也便是说“=”是MSP430汇编中数据分配伪指令中的一种。咱们来看一下MSP430汇编的数据分配伪指令有哪些:
这类指令有以下一些:
SET (VAR, ASSIGN) 赋予一个临时值;
EQU (=) 在当时模块中赋予一个永久的值;
DEFINE 界说一个整个文件中都有用的值;
sfrb 寄存器类型的字节;
sfrw 寄存器类型的字。
运用语法如下:
label SET expr
label EQU expr
label = expr
label DEFINE expr
[const] sfrb register = value
[const] sfrw register = value
其间,
label 界说一个标志符、
expr 标志符的值、
register 特别功用寄存器、
value 特别功用寄存器的值。
鄙人面的比如中运用了局部变量与全局变量,在模块add1 中界说了符号value ,同样在
模块add2 中也界说了符号value,但它们表明两个不同的量,都只在各自的模块内部有用,
这是局部变量。而在模块add1 中界说的locn 则为全局变量,在两个模块中表明同一个值。
NAME add1
locn DEFINE 100H
value EQU 77
MOV locn,R4
ADD #value,R4
ENDMOD
NAME add2
value EQU 88
MOV locn,R5
ADD #value,R5
END
很明显,“=”也便是EQU,效果是:在当时模块中赋予一个永久的值。
至此,
#define DEFCW(name, address) __no_init union
{
struct
{
volatile unsigned char name##_L;
volatile unsigned char name##_H;
};
volatile unsigned short name;
} @ address;
这种界说也变得相对好了解。以上的这种界说仅仅多了一个union的界说,将一个16位的地址存储空间分红2个8bits或许1个16位。能够完成字拜访,也能够完成字节拜访。以上界说是将一个无名的union与address联系起来,使得拜访address对应的内存时,就像拜访union相同。
那么关于下面的一些看起来形似比较复杂的界说就相对比较好了解了:
#define RF1AIFCTL1_ (0x0F02u)
DEFCW( RF1AIFCTL1 , RF1AIFCTL1_)
#define RF1AIFIFG RF1AIFCTL1_L
#define RF1AIFIE RF1AIFCTL1_H
能够发现,第一个宏界说,“RF1AIFCTL1_”在字符串的最终带一个下划线,其实代表这仅仅一个地址。而经过宏扩展DEFCW( RF1AIFCTL1 , RF1AIFCTL1_),将会被扩展为:
__no_init union
{
struct
{
volatile unsigned char RF1AIFCTL1_L;
volatile unsigned char RF1AIFCTL1_H;
};
volatile unsigned short RF1AIFCTL1;
} @ (0x0F02u);
关于@的用法,今日查阅了《MSP430 IAR C/EC++ Compiler Reference Guide》,找到了成果:
A variable that has been explicitly placed at an address, for example by using the compiler @ syntax, will be placed in either the DATA16_AC or the DATA16_AN segment.
从中能够看出,@是一种语法。那么它的效果很明显便是将变量放置到对应的地址中。运用@,一个变量能够清晰的拟定一个存储地址。
因而之前的宏界说就变得好了解了。
#define DEFC(name, address) __no_init volatile unsigned char name @ address;
便是将name变量寄存在address地址中,那么如此一来就能够为每个寄存器进行命名了,也便是说能够完成每个寄存器对应一个或许多个变量。
至此头文件中别的一个问题也方便的解决:
#define RF1AIFCTL1_ (0x0F02u)
DEFCW( RF1AIFCTL1 , RF1AIFCTL1_)
#define RF1AIFIFG RF1AIFCTL1_L
#define RF1AIFIE RF1AIFCTL1_H
咱们将DEFCW( RF1AIFCTL1 , RF1AIFCTL1_)打开:
__no_init union
{
struct
{
volatile unsigned char RF1AIFCTL1_L;
volatile unsigned char RF1AIFCTL1_H;
};
volatile unsigned short RF1AIFCTL1;
} @ (0x0F02u);
那么能够知道,RF1AIFCTL1,RF1AIFCTL1_L,RF1AIFCTL1_H现已声明成为一个变量,寄存的地址分别是0x0F02u,0x0F02u+1,0x0F02u。因而接下来后边两条宏界说就天然的解开了。
#define RF1AIFIFG RF1AIFCTL1_L
#define RF1AIFIE RF1AIFCTL1_H
功用仅仅为变量RF1AIFCTL1_L,RF1AIFCTL1_H界说了别的的一种姓名作为替换。