stm32中的「位帶操作」淺析
(既然是stm32的相關解析,則默認讀者已掌握C語言基礎)
stm32中,一個地址單元就是一個位元組,即一個地址為8bit。
stm32基於Cortex-M3內核,通俗地講,位帶操作就是把位帶區中一個地址的8個位分別映射到位帶別名區的8個地址(LSB有效,即最低位有效),通過操作相應地址的方式實現操作某個位,如圖1-1。其支持位帶操作的兩個內存區域為:
- SRAM區:0x20000000 ~ 0x200FFFFF,最低1M範圍;
- 片上外設區: 0x40000000 ~ 0x400FFFFF,最低1M範圍;
那麼,應該如何換算位帶區里每一位對應的別名區地址呢?有一個公式可用。
- 別名區地址 = 別名區起始地址 + (位位元組地址偏移量 * 8 + n) * 4(以位元組為單位時,n∈[0,7];以字為單位時,n∈[0,31])
則兩個區的計算公式為:
- SRAM區:別名區地址 = 0x22000000 + (A - 0x20000000)* 32 + n * 4
- 片上外設區:別名區地址 = 0x42000000 + (A - 0x40000000)* 32 + n * 4
其中,
A:位帶區位元組地址(GPIOx_BASE+偏移地址);
n:操作位號;「*32」:前文提到,位帶區每1位膨脹為別名區里一個32位的字,1字=4位元組=32bit;「*4」:1字=4位元組
我們以GPIOA為例,GPIOA.0~GPIOA.7設置推挽輸出、最大速度50MHz(0011); GPIOA.8~GPIOA.15設置浮空輸入(0100):
GPIOA->CRL = 0x33333333;nGPIOA->CRH = 0x44444444; n
接下來,進行簡單的操作,使輸入狀態反應到輸出狀態,利用公式:
typedef unsigned long u32;nnu32 *PAO3 = (u32 *)(0x42000000 + (GPIOA_BASE+Ox0C - 0x40000000) * 32 + 3 * 4);//輸出nu32 *PAI11 = (u32 *)(0x42000000 + (GPIOA_BASE+Ox09- 0x40000000) * 32 + 3 * 4);//輸入n//u32 *PAI11 = (u32 *)(0x42000000 + (GPIOA_BASE+Ox08 - 0x40000000) * 32 + 11 * 4);//輸入nnif(*PAI11 == 1){n *PAO3 = 1;n}else{n *PAO3 = 0;n}n
通過查手冊可知,GPIOA_ODR地址偏移為0Ch(h表示十六進位),GPIOA_IDR地址偏移為0x08,則可得出各自的偏移量。由於GPIOx_IDR佔用了兩個位元組的地址,第11位在第二個地址,所以地址偏移應為:
0x10808+1 = 0x10809
所以,代碼里的兩種方式都可以。
以上代碼得出了IDR寄存器在第11位的別名區地址和ODR寄存器在第3位的別名區地址,最後在debug時,通過操作輸入埠相應位,程序判斷輸入埠狀態值,設置LSB值為1或0(任意的奇數或偶數),進而操作輸出埠狀態,實現了如同51單片機里簡便的操作。如圖1-2:
看到這裡,應該對Cortex-M3里的位帶操作有了大概的了解了吧,別急,還沒結束,有不只一組GPIO埠,每組GPIO也都有不只一個引腳,這麼多的引腳難道要一個個照公式寫嗎,很明顯這不太現實。所以,我們使用宏定義的方式來簡化操作,做完這一步,則一勞永逸。
直接上代碼:
#define GPIOA_ODR (GPIOA_BASE + 0x0C) //位帶區位元組地址,即為公式中的「A」n#define GPIOA_IDR (GPIOA_BASE + 0x08)n...n#define GPIOE_ODR (GPIOE_BASE + 0x0C)n#define GPIOE_IDR (GPIOE_BASE + 0x08)nn#define BitBand(Addr, BitNum) *((volatile unsigned long *)((Addr & 0xF0000000) + 0x2000000 + ((Addr & 0xFFFFF) << 5) + (BitNum << 2))) //表達式n n#define PAout(n) BitBand(GPIOA_ODR, n) //輸出n#define PAin(n) BitBand(GPIOA_IDR, n) //輸入nnif(PAin(12) == 1){n PAout(4) = 1;n}else{n PAout(4) = 0;n}n
--------------------------------------------------------------------
文章首發於知乎,轉載請私信,並註明原文出處。
推薦閱讀:
※CPU寄存器到底有多大?《深入理解計算機系統》說大概有幾百位元組,可是彙編課上卻說理論上有64kb
TAG:寄存器 |