幾個操作寄存器常用的宏


本文地址:https://www.cnblogs.com/jqdy/p/14385295.html

  操作寄存器時經常用到令某位等於零或者等於一,還有令連續的幾位等於某個值,等等這樣的操作。

  按照一般的做法,比如讓某個寄存器的 B1 位等於一時,會“或”上0x02,每次總是反復確認是否正確;換成和(1<<1)進行“或”操作后,雖然簡單明了保證不出錯了,但是左移一位到底代表什么,時間長了還得去查手冊。

  因此,編了幾個宏替代上述操作,簡單明了,又不會出錯:

  1. 讓某個寄存器的其中一位等於1

  寄存器的8個位 B7 ~ B0, 其中,__M__表示 BX中的X,恰好和手冊中寄存器位定義表表頭中的次序一樣。

  為了進一步提高位操作的可讀性,將寄存器的各個位的次序也進行宏定義。

1 /*將寄存器 REGISTER 的 M 位 置1。M 取值 0 ~ 7*/
2 #define SET_BIT(__REGISTER__, __M__) do{__REGISTER__ |= (1 << __M__);}while(0)
3 
4 //本宏的意思,就是將I2CCFG寄存器的 B7 位 ENI2C 置 1,顧名思義就是將I2CCFG寄存器中的I2C使能位置位
5 SET_BIT(I2CCFG, ENI2C_BIT);

   寄存器位次序宏定義片段:

1 // S4CON(84H)
2 #define S4SM0_BIT    7
3 #define S4ST4_BIT    6
4 #define S4SM2_BIT    5
5 #define S4REN_BIT    4
6 #define S4TB8_BIT    3
7 #define S4RB3_BIT    2
8 #define S4TI_BIT     1
9 #define S4RI_BIT     0

  2. 讓某個寄存器的其中一位等於 0

1 /*將寄存器 REGISTER 的 M 位清零。M 取值 0 ~ 7*/
2 #define CLEAR_BIT(__REGISTER__, __M__) do{__REGISTER__ &= (~(1 << __M__));}while(0)

  3. 單獨取出某寄存器中的一位的值

1 /*將寄存器 REGISTER 的 M 位取出。M 取值 0 ~ 7*/
2 #define GET_BIT(__REGISTER__, __M__) (__REGISTER__ & (1 << __M__))

  4. 將寄存器中連續幾位清零

/*將寄存器 REGISTER 從 M 位到 N 位清零。M 和 N 取值 0 ~ 7,且 M > N*/
#define CLEAR_BITS(__REGISTER__, __M__, __N__)\
  do{\
    __REGISTER__ &= (~((0xffU >> (7 - __M__ + __N__)) << __N__));\
  }while(0)

  以將B5~B3連續3位清零為例,說明該宏的思路:

  將B5、B4、B3連續3位清零,就是把寄存器和 C7H(1100 0111B)相“與”。其中 1100 0111B 中的 B 是借用 16進制數表示法 C7H 中 H的作用,表示二進制數。

  上邊的 1100 0111B = C7H = ~(0011 1000B)  = ~(38H)。

  到這里就出現了和單一位清零類似的局面,就是把 1 左移幾位,再取反,最后和寄存器的值相“與”,即 REGISTER &= ~(0x38)。

  那么接下來的問題就是,在宏代碼中連續3個“1”怎么得到,以及左移3位怎么得到:

  • 得到連續 3 個 1:將連續8個1,即 0xff 右移 5 次,就得到了 “111”,即:5 = 8 - 5 + 3 - 1 = (8 - 1) - 5 + 3 = 7 - 5 + 3。這樣,宏表達式中的 7 - __M__ + __N__ 就代表着將 0xff 右移 5 次。
  • 左移3位:很簡單,這里的 3 就是 B3 的次序號。

  完整表達下來就是:CLEAR_BITS(P1M1, 5, 3),這里的 REGISTER 是 P1M1 這個寄存器。

  對於8位單片機,表達式中使用0xff,對於16、32位單片機,換成0xffff、0xffffffff。

  5. 將寄存器中的連續幾位賦新值

/*將寄存器 REGISTER 從 M 位到 N 位賦值為 NEW。M 和 N 取值 0 ~ 7,且 M > N*/
#define LET_BITS(__REGISTER__, __M__, __N__, __NEW__)\
  do{\
    CLEAR_BITS(__REGISTER__, __M__, __N__);\
    __REGISTER__ |= (__NEW__ << __N__);\
  }while(0)

  將寄存器中的連續幾個位賦值,要分成兩步走,首先需將這幾位清零,然后再將新值左移適當的次數后,再與寄存器的值相“或”即可。

  還用上面哪個例子,將 B5 ~ B3 連續3位賦值為 101 (0x05):

  • 將 B5~B3位清零:借用 “4.將寄存器中連續幾位清零”一節中的 CLEAR_BITS(P1M1, 5, 3)即可
  • 將新值101(0x05)左移3位(3即為B3的次序號),再和寄存器的值相“或”:P1M1 |= (0x05 << 3),這就是宏定義中的 __REGISTER__ |= (__NEW__ << __N__)

   整體效果是這樣的:LET_BITS(P1M1, 5, 3, 0x05)。

 

  另外,還有一個宏是令寄存器的連續幾位都等於1,不過不太常用:

/*將寄存器 REGISTER 從 M 位到 N 位置位。M 和 N 取值 0 ~ 7,且 M > N*/
#define SET_BITS(__REGISTER__,__M__,__N__)\
    do{\
        __REGISTER__|=((0xffU>>(7-__M__+__N__))<<__N__);\
    }while(0)  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM