| 1 定義首先需要明確下,位段,位帶和別名區(qū)這三個(gè)名詞 位段:STM32用戶參考手冊(cè)使用的名字 位帶:CortexM3參考手冊(cè)使用的 別名區(qū):地址總線上用來(lái)位訪問(wèn)地址區(qū)域, 
 所以說(shuō),位段和位帶是一個(gè)意思,是不同手冊(cè)的不同叫法。 由上述的名詞解釋得知,位帶功能并不是STM32獨(dú)有的,是CortexM3的功能(CortexM4也有這樣的功能)。MCS51有位操作,以一位(bit)為數(shù)據(jù)對(duì)象的操作,MCS51可以簡(jiǎn)單的將P1口的第2位獨(dú)立操作:P1.2=0;P1.2=1 ;這樣就把P1口的第三個(gè)腳(bit2)置0置1。而STM32的位段、位帶別名區(qū)最重要的就為了實(shí)現(xiàn)這樣的功能。 2 位帶操作2.1 范圍位帶是有范圍的,并不是CortexM3全部地址空間都支持的。在 CM3中,有兩個(gè)區(qū)中實(shí)現(xiàn)了位帶。其中一個(gè)是 SRAM 區(qū)的最低 1MB 范圍,第二個(gè)則是片內(nèi)外設(shè)區(qū)的最低 1MB 范圍。這兩個(gè)區(qū)中的地址除了可以像普通的 RAM 一樣使用外,它們還都有自己的“位帶別名區(qū)”,位帶別名區(qū)把每個(gè)比特膨脹成一個(gè) 32 位的字。當(dāng)你通過(guò)位帶別名區(qū)訪問(wèn)這些字時(shí),就可以達(dá)到訪問(wèn)原始比特的目的。 支持位帶操作的兩個(gè)內(nèi)存區(qū)的范圍是: 
 0x2000_0000‐0x200F_FFFF(SRAM 區(qū)中最低1MB區(qū)域) 0x4000_0000‐0x400F_FFFF(片上外設(shè)區(qū)中的最低 1MB) 
 2.2 位帶操作對(duì) SRAM 位帶區(qū)的某個(gè)比特,記該比特所在字節(jié)的地址為A,位序號(hào)為 n (0<=n<=7),則它在別名區(qū)的地址為: 對(duì)于片上外設(shè)位帶區(qū)的某個(gè)比特,記該比特所在字節(jié)的地址為A,位序號(hào)為 n (0<=n<=7),則該比特在別名區(qū)的地址為: 上式中,“*4”表示一個(gè)字為 4 個(gè)字節(jié),“*8”表示一個(gè)字節(jié)中有 8 個(gè)比特。 
 2.3代碼實(shí)現(xiàn)把“位帶地址+位序號(hào)”轉(zhuǎn)換別名地址宏為: #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2))把該地址轉(zhuǎn)換成一個(gè)指針: #define MEM_ADDR(addr, bitnum) *((volatile unsigned long *)((addr & 0xF0000000)+0x2000000 + ((addr &0xFF FFF)<<5) + (bitnum<<2)))其中 addr的取值范圍: 0x2000_0000‐0x200F_FFFF 0x4000_0000‐0x400F_FFFF 注意:addr取值要32位對(duì)齊 bitnum的取值范圍:0-31 
 解析: (addr & 0xf0000000) + 0x02000000: 區(qū)分SRAM還是外設(shè),如果是外設(shè),結(jié)果為4,再加0x2000000就等于0x4200000,0x42000000就是外設(shè)別名位帶區(qū)。如果是SRAM,結(jié)果為2,再加上0x2000000就等于0x22000000,0x22000000就是SRAM別名位帶區(qū)。 
 addr & 0x00ffffff: 屏蔽了最高2位,相當(dāng)于減去0x20000000或者0x40000000。因?yàn)槲粠^(qū)的有效范圍是1M,即0x100000,這樣子就做到了低6位有效。 
 << 5: 等價(jià)于乘以32 
 << 2: 等價(jià)于乘以4 
 特別提醒: 當(dāng)你使用位帶功能時(shí),要訪問(wèn)的變量必須用 volatile 來(lái)定義。因?yàn)?C 編譯器并不知道同一個(gè)比特可以有兩個(gè)地址。所以就要通過(guò) volatile,使得編譯器每次都如實(shí)地把新數(shù)值寫(xiě)入存儲(chǔ)器,而不再會(huì)出于優(yōu)化的考慮。 3 位段的優(yōu)點(diǎn)最容易想到的就是通過(guò) GPIO 的管腳來(lái)單獨(dú)控制每盞 LED 的點(diǎn)亮與熄滅。另一方面,也對(duì)操作串行接口器件提供了很大的方便(典型如 74HC165,CD4094)。位帶操作可以把代碼縮小, 速度更快,效率更高,更安全??傊粠Р僮鲗?duì)于硬件 I/O 密集型的底層程序最有用處了 位帶操作還能用來(lái)化簡(jiǎn)跳轉(zhuǎn)的判斷。 當(dāng)跳轉(zhuǎn)依據(jù)是某個(gè)位時(shí),以前必須這樣做 1、讀取整個(gè)寄存器 2、掩蔽不需要的位 3、比較并跳轉(zhuǎn) 使用位帶操作后 1、從未帶別名區(qū)讀取狀態(tài)位 2、比較并跳轉(zhuǎn) 
 當(dāng)然,對(duì)于寫(xiě)入操作也從4步精簡(jiǎn)到3步 
 
 | 
|  | 
來(lái)自: 新進(jìn)小設(shè)計(jì) > 《待分類》