STM32中的位帶 bit band 操作

2021-07-15 05:47:09 字數 3689 閱讀 4242

支援了位帶操作後,可以使用普通的載入/儲存指令來對單一的位元進行讀寫。在 cm3 中,有兩個區中實現了位帶。其中乙個是 sram 區的最低 1mb 範圍,第二個則是片內外設區的最低 1mb範圍。這兩個區中的位址除了可以像普通的 ram 一樣使用外,它們還都有自己的「位帶別名區」,位帶別名區把每個位元膨脹成乙個 32 位的字。當你通過位帶別名區訪問這些字時,就可以達到訪問原始位元的目的。

位帶操作的概念其實 30 年前就有了,那還是8051 微控制器開創的先河,如今,cm3 將此能力進化,這裡的位帶操作是 8051 位定址區的威力大幅加強版。

位帶區:支援位帶操作的位址區

位帶別名:對別名位址的訪問最終作用到位帶區的訪問上(這中途有乙個位址對映過程)

在位帶區中,每個位元都對映到別名位址區的乙個字——這是只有 lsb 有效的字。當乙個別名位址被訪問時,會先把該位址變換成位帶位址。對於讀操作,讀取位帶位址中的乙個字,再把需要的位右移到 lsb,並把 lsb 返回。對於寫操作,把需要寫的位左移至對應的位序號處,然後執行乙個原子的「讀-改-寫」過程。

支援位帶操作的兩個記憶體區的範圍是:

0x2000_0000‐0x200f_ffff(sram 區中的最低 1mb)

0x4000_0000‐0x400f_ffff(片上外設區中的最低 1mb)

對 sram 位帶區的某個位元,記它所在位元組位址為 a,位序號為 n(0<=n<=7),則該位元在別名區的位址為:

aliasaddr=0x22000000+((a-0x20000000)*8+n)*4=0x22000000+(a-0x20000000)*32+n*4

對於片上外設位帶區的某個位元,記它所在位元組的位址為 a,位序號為 n(0<=n<=7),則該位元在別名區的位址為:

aliasaddr=0x42000000+((a-0x40000000)*8+n)*4=0x42000000+(a-0x40000000)*32+n*4

上式中,「*4」表示乙個字為 4 個位元組,「*8」表示乙個位元組中有 8 個位元。

這裡再不嫌囉嗦地舉乙個例子:

1. 在位址 0x20000000 處寫入 0x3355aacc

2. 讀取位址0x22000008。本次讀訪問將讀取 0x20000000,並提取位元 2,值為 1。

3. 往位址 0x22000008 處寫 0。本次操作將被對映成對位址 0x20000000 的「讀-改-寫」操作(原子的),把位元2 清 0。

4. 現在再讀取 0x20000000,將返回 0x3355aac8(bit[2]已清零)。

位帶別名區的字只有 lsb 有意義。另外,在訪問位帶別名區時,不管使用哪一種長度的資料傳送指令(字/半字/位元組),都把位址對齊到字的邊界上,否則會產生不可預料的結果。 

[cpp]view plain

copy

/////位帶操作,實現51類似的gpio控制功能

//具體實現思想,參考<

//io口操作巨集定義

#define bitband(addr, bitnum) ((addr & 0xf0000000)+0x2000000+((addr &0xfffff)<<5)+(bitnum<<2)) 

#define mem_addr(addr)  *((volatile unsigned long  *)(addr)) 

#define bit_addr(addr, bitnum)   mem_addr(bitband(addr, bitnum)) 

//io口位址對映

#define gpioa_odr_addr    (gpioa_base+12) //0x4001080c 

#define gpiob_odr_addr    (gpiob_base+12) //0x40010c0c 

#define gpioc_odr_addr    (gpioc_base+12) //0x4001100c 

#define gpiod_odr_addr    (gpiod_base+12) //0x4001140c 

#define gpioe_odr_addr    (gpioe_base+12) //0x4001180c 

#define gpiof_odr_addr    (gpiof_base+12) //0x40011a0c    

#define gpiog_odr_addr    (gpiog_base+12) //0x40011e0c    

#define gpioa_idr_addr    (gpioa_base+8) //0x40010808 

#define gpiob_idr_addr    (gpiob_base+8) //0x40010c08 

#define gpioc_idr_addr    (gpioc_base+8) //0x40011008 

#define gpiod_idr_addr    (gpiod_base+8) //0x40011408 

#define gpioe_idr_addr    (gpioe_base+8) //0x40011808 

#define gpiof_idr_addr    (gpiof_base+8) //0x40011a08 

#define gpiog_idr_addr    (gpiog_base+8) //0x40011e08 

//io口操作,只對單一的io口!

//確保n的值小於16!

#define paout(n)   bit_addr(gpioa_odr_addr,n)  //輸出 

#define pain(n)    bit_addr(gpioa_idr_addr,n)  //輸入 

#define pbout(n)   bit_addr(gpiob_odr_addr,n)  //輸出 

#define pbin(n)    bit_addr(gpiob_idr_addr,n)  //輸入 

#define pcout(n)   bit_addr(gpioc_odr_addr,n)  //輸出 

#define pcin(n)    bit_addr(gpioc_idr_addr,n)  //輸入 

#define pdout(n)   bit_addr(gpiod_odr_addr,n)  //輸出 

#define pdin(n)    bit_addr(gpiod_idr_addr,n)  //輸入 

#define peout(n)   bit_addr(gpioe_odr_addr,n)  //輸出 

#define pein(n)    bit_addr(gpioe_idr_addr,n)  //輸入

#define pfout(n)   bit_addr(gpiof_odr_addr,n)  //輸出 

#define pfin(n)    bit_addr(gpiof_idr_addr,n)  //輸入

#define pgout(n)   bit_addr(gpiog_odr_addr,n)  //輸出 

#define pgin(n)    bit_addr(gpiog_idr_addr,n)  //輸入

STM32 位帶應用

from cortex m3 支援了位操作後,可以使用普通的載入 儲存指令來對單一的位元進行讀寫。在 cm3 支援的位帶中,有兩個區中實現了位帶。其中乙個是 sram區的最低 1mb 範圍,0x20000000 0x200fffff sram 區中的最低 1mb 第二個則是片內外設區的最低 1mb範...

STM32中的位帶 bit band 操作

支援了位帶操作後,可以使用普通的載入 儲存指令來對單一的位元進行讀寫。在 cm3 中,有兩個區中實現了位帶。其中乙個是 sram 區的最低 1mb 範圍,第二個則是片內外設區的最低 1mb範圍。這兩個區中的位址除了可以像普通的 ram 一樣使用外,它們還都有自己的 位帶別名區 位帶別名區把每個位元膨...

STM32中的位帶 bit band 操作

位帶操作,實現51類似的gpio控制功能 具體實現思想,參考 io口操作巨集定義 define bitband addr,bitnum addr 0xf0000000 0x2000000 addr 0xfffff 5 bitnum 2 define mem addr addr volatile un...