先上源代碼:
文件為portmacro.h,來源於Dynasty項目中的底層代碼(NVIC中斷控制部分)
1 #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
2 #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
3
4
5 void vPortYield( void ) 6 { 7 /* Set a PendSV to request a context switch. */
8 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; 9
10 /* Barriers are normally not required but do ensure the code is completely 11 within the specified behaviour for the architecture. */
12 __DSB(); 13 __ISB(); 14 }
這一句讓我懵逼了.
1 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
宏定義還可以賦值!!?以往的認知都是宏定義為常量,常量不可以被賦值,所以宏一般都是出現在操作符的右側!!
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
雖然這句話我可以看懂,portNVIC_INT_CTRL_REG 代表 0xe000ed04UL 地址中的值。為了驗證,測試程序如下
1 #define MACRO_A ( * ( ( volatile uint32_t * ) 0x20000300 ) )
2 #define MACRO_B 200
3 #define MACRO_C (a)
4
5 int a = 10; 6
7 void MacroTest() 8 { 9 int nVal = 50; 10
11 PWAPP_TRACE(("MACRO_C: %d", MACRO_C)); 12
13 MACRO_C = 20; 14 PWAPP_TRACE(("MACRO_C: %d", MACRO_C)); 15 PWAPP_TRACE(("MACRO_A: %d", MACRO_A)); 16 PWAPP_TRACE(("address: %d",( * ( ( volatile uint32_t * ) 0x20000300 )) )); 17 MACRO_A = MACRO_B; 18
19 PWAPP_TRACE(("MACRO_A: %d", MACRO_A)); 20 PWAPP_TRACE(("MACRO_B: %d", MACRO_B)); 21
22 MACRO_A = nVal; 23 PWAPP_TRACE(("MACRO_A: %d", MACRO_A)); 24
25 return; 26 }
測試的結果為:
[PWAPP][MacroTest], line[1230]>>>MACRO_C: 20
[PWAPP][MacroTest], line[1233]>>>MACRO_C: 20
[PWAPP][MacroTest], line[1235]>>>MACRO_A: 50
[PWAPP][MacroTest], line[1236]>>>address: 0
[PWAPP][MacroTest], line[1240]>>>MACRO_A: 200
[PWAPP][MacroTest], line[1241]>>>MACRO_B: 200
[PWAPP][MacroTest], line[1244]>>>MACRO_A: 50
結果顯示還真是可以給宏賦值。
貼上宏的定義:
計算機科學里的宏(Macro),是一種批量批處理的稱謂。一般說來,宏是一種規則或模式,或稱語法替換 ,用於說明某一特定輸入(通常是字符串)如何根據預定義的規則轉換成對應的輸出(通常也是字符串)。這種替換在預編譯時進行,稱作宏展開。
發現定義中有意思的點在於這個“語法替換”,。
當宏定義值本身為常量時,這個宏就替換為一個常量,
如:“#define MACRO_B 200”,MACRO_B就不可以被重新賦值。
當宏定義本身代表了一個變量時,這個宏就替換了這個變量,也就同時擁有了該變量可以被賦值的特點,
如
“#define MACRO_C (a)
int a = 10;”
此時MACRO_C代替了整形變量a,同時MACRO_C也可以被賦值。
而#define MACRO_A ( * ( ( volatile uint32_t * ) 0x20000300 ) )實質上和#define MACRO_C (a)是一樣的。 * ( ( volatile uint32_t * ) 0x20000300 和a代表的相同的意思。
所以,MARCO是否能夠在之后的代碼中被賦值,取決於宏在被定義時代表的是常量還是變量。
其實還有一個很重要的應用問題,雖然MACRO可以被重新賦值,但是在實際代碼中使用MACRO來代替變量是否合適呢?也就說應用場景有哪些?
常有的用法一般都是用宏來代替常量,因為宏的定義可以清楚的表示該常量的意義。
而 #define MACRO_A ( * ( ( volatile uint32_t * ) 0x20000300 ) ) 這種用法的個人猜測意義在於可以直接訪問硬件地址或驅動的寄存器,在底層的代碼中應用的機會會比較多。同時也可以讓開發者清楚的知道該地址的意義。如之前的
1 #define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04UL ) )
就是NVIC驅動控制寄存器的代表。
目前關於這種宏賦值的用法能想到的基本就只有這些,可能還有其他的應用場景,希望大家能夠補充~
最后祝大家身體健康~
