新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 位帶操作在stm32中的C語言實(shí)現(xiàn)

位帶操作在stm32中的C語言實(shí)現(xiàn)

作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
首先:

本文引用地址:http://m.butianyuan.cn/article/201611/318096.htm

#define BITBAND(addr,bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))

對上句程序的解釋:

利用宏定義的方式將位帶地址的映射表示出來,該函數(shù)有兩個(gè)參數(shù)addr和bitnum,分別是原本的地址和在數(shù)據(jù)中的第幾位。我們知道兩個(gè)公式如下:

0x2000_0000‐0x200F_FFFF地址空間:AliasAddr = 0x22000000 + (A – 0x20000000)*32 + n*4

0x4000_0000‐0x400F_FFFF地址空間:AliasAddr = 0x42000000 + (A – 0x40000000)*32 + n*4

仔細(xì)觀察我們可以發(fā)現(xiàn),是有規(guī)律可尋的。兩個(gè)公式的基地址一個(gè)是0x22000000,一個(gè)是0x42000000,他們只是最高位不一樣,這個(gè)最高位和最原始的地址的最高位是一致的。所以我們通過 (addr & 0xF0000000) 來取最高位,再加上0x2000000就得到了公式中的基地址。我們知道兩個(gè)地址空間中地址的變換只是在低5位上,比如0x2000_0000 — 0x200F_FFFF(有5個(gè)F),利用(A – 0x20000000)的目的是得到地址addr和0x2000_0000之間的偏移,也就是低5位的內(nèi)容,所以我們通過 (addr & 0xFFFFF)得到了低5位的數(shù)據(jù),也即是偏移量。公式中的乘以32,我們使用效率更高的左移5位,同理,之后的乘以4也是通過移位操作來實(shí)現(xiàn)的。

然后我們需要將上述地址轉(zhuǎn)換為一個(gè)指針,也就是,我們要告訴編譯器這是一個(gè)地址。

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

其中使用到的volatile這個(gè)關(guān)鍵字是為了防止編譯器進(jìn)行優(yōu)化。這是必須的。

完成上述兩步之后,我們就可以使用位帶操作了,比如我們要對GPIOA中的1管腳進(jìn)行輸出控制,我們需要控制GPIOA的ODR寄存器,通過手冊我們知道它的地址是(GPIOA_BASE + 0x0C),所以我們定義:

#define GPIOA_ODR_Addr (GPIOA_BASE + 0x0C)

#define GPIOA(BitNum) MEM_ADDR( BITBAND(GPIOA_ODR_Addr,BitNum))

將GPIOA的1管腳置高,就可以這樣寫:

GPIOA(1) = 1;

同理,我們可以得到其他管腳控制的方法,或者獲取其他管腳的輸入。

以上,就是我對stm32的位帶操作的實(shí)現(xiàn)的理解,有什么理解不到位的地方,請大家指證,希望和大家多多交流。



評論


技術(shù)專區(qū)

關(guān)閉