STM32 的位帶操作

位操作就是可以單獨的對一個比特位進行讀和寫,這個在51單片機中非常常見。51單片機中通過關鍵字sbit來實現位定義,STM32中則是通過訪問位帶別名區的地址來實現對某一位的操作。

例如51單片機中可以實現以下操作

#define LED_ON 0
sbit LED = P2^0;
LED = LED_ON;

而現在STM32的位段、位帶別名區就爲了實現這樣的功能。STM32針對SRM和外設區開闢了兩個內存空間(位帶區),分別是SRAM和外社區的最低1MB的空間。這兩個1MB的內存空間除了可以像正常的 RAM 一樣操作外,他們還有自己的位帶別名區,位帶別名區就是把1MB位帶區的每一個位膨脹成一個32位的字,當通過訪問位帶別名區的這些字時,就可以達到訪問位帶區某個比特位的目的。位帶區的一個比特位經過膨脹之後,雖然變大到 4個字節,但是還是 LSB纔有效。

由上圖可以看出STM32 支持位帶操作的兩個內存區的範圍是: 
 0x2000_0000‐0x200F_FFFF(SRAM 區中的最低1MB) 

0x4000_0000‐0x400F_FFFF(片上外設區中的最低1MB)

我們可以通過指針的形式訪問位帶別名區地址從而達到操作位帶區比特位的效果。

位帶別名區地址公式爲

AliaAddr(addr,bitnum) = (addr&0xF0000000) + 0x2000000 + (addr&0xFFFFF)<<5 + bitnum<<2

ADDR爲該比特位所在字節的地址,Bitnum爲位序號

 

這裏我以操作一個ODR寄存器(對於GPIO基地址的偏移爲20)爲例

例如

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))           // 把一個地址轉換成一個指針 
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))       // 把位帶別名區地址轉換成指針
#define GPIOH_ODR_Addr (GPIOH_BASE+20)                               //寄存器地址映射
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n)                          //輸出

/*主函數
    * @beief 電亮LED燈
    * @param 無 
    * @revel 無
    */
int main
{
    LED_Config();                                                    //LED燈GPIO配置
    PHout(10) = 0;                                                   //點亮LED燈

}

關於主函數的點亮LED的操作,請參照stm32f4固件庫函數點亮LED燈

關於爲什麼不直接對STM32的位帶區進行位操作原因是STM32對內存的控制讀寫數據是按字節來算的,不能對一位進行直接操作。

位操作有如下優點

位帶操作可以把代碼縮小, 速度更快,效率更高,更安全。 
一般操作要6條指令,而使用 位帶別名區只要4條指令。    
 一般操作是  讀-改-寫  的方式, 而位帶別名區是 寫 操作。防止中斷對讀-改-寫  的方式的影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章