標題:
IAR 430 頭文件中#define定義的部分解釋
[打印本頁]
作者:
51黑黑黑
時間:
2016-2-12 20:50
標題:
IAR 430 頭文件中#define定義的部分解釋
今天在閱讀
RF_Example_Code_v1.0
中頭文件
cc430x613x.h
時發(fā)現了幾部分的疑問。
首先來看一下
cc430x613x.h
中的
3
個
#define
的例子:
#define DEFC(name, address) __no_init volatile unsigned charname @ address;
#define DEFW(name, address) __no_init volatile unsigned shortname @ 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
的用法是一樣的。首先我可以發(fā)現,在宏定義里面都有一個關鍵字
__no_init
。查看了《
MSP430IAR C/EC++ Compiler Reference Guide
》內的
IAR Language Extension Overview
可以發(fā)現,
__no_init
是
IAR
擴展語法里面的一個擴展關鍵字。作用是聲明一個
non-volatile
類型的內存地址(
Supportnon-valotile memory
)。
于是解決了
__no_init
的問題。
再者對
@
這個字符存在一定的疑問,于是上網查了查資料。雖然對于
@
這個字符的用法還是不是很明確,但是可以明確的是:
#define DEFC(name, address) __no_init volatile unsigned charname @ address;
#define DEFC(name, address) sfrb name = address;
這兩種定義是等價的,但是后者是基于匯編嵌入式編程的情況下才成立。也就是說“
=
”是
MSP430
匯編中數據分配偽指令中的一種。我們來看一下
MSP430
匯編的數據分配偽指令有哪些:
這類指令有以下一些:
SET (VAR, ASSIGN)
賦予一個臨時值;
EQU (=)
在當前模塊中賦予一個永久的值;
DEFINE
定義一個整個文件中都有效的值;
sfrb
寄存器類型的字節(jié);
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
位?梢詫崿F字訪問,也可以實現字節(jié)訪問。以上定義是將一個無名的
union
與
address
聯系起來,使得訪問
address
對應的內存時,就像訪問
union
一樣。
那么對于下面的一些看起來貌似比較復雜的定義就相對比較好理解了:
#define RF1AIFCTL1_ (0x0F02u)
DEFCW( RF1AIFCTL1 , RF1AIFCTL1_)
#define RF1AIFIFG RF1AIFCTL1_L
#define RF1AIFIE RF1AIFCTL1_H
可以發(fā)現,第一個宏定義,“
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++ CompilerReference Guide
》,找到了結果:
A variable that has been explicitly placed at an address, forexample by using the compiler @ syntax, will be placed in eitherthe DATA16_AC or the DATA16_AN segment.
從中可以看出,
@
是一種語法。那么它的作用很明顯就是將變量放置到對應的地址中。使用
@
,一個變量可以明確的制定一個存儲地址。
因此之前的宏定義就變得好理解了。
#define DEFC(name, address) __no_init volatile unsigned charname @ 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
定義了另外的一種名字作為替換。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1