關(guān)于STM32的GPIO輸入輸出的位帶操作
支持位帶操作的兩個內(nèi)存區(qū)的范圍是:
0x2000_0000‐0x200F_FFFF(SRAM區(qū)中的最低1MB)
0x4000_0000‐0x400F_FFFF(片上外設(shè)區(qū)中的最低1MB)
位帶操作可以在不加任何特殊指令時實現(xiàn)位操作。在對一個外設(shè)寄存器或者SRAM進行位操作時,需要計算與其對應(yīng)的位帶別名區(qū)中的地址。計算公式如下:
位帶別名區(qū)地址=位帶別名區(qū)基地址+字偏移地址
字偏移地址=字節(jié)相對位帶區(qū)的偏移
位31:16保留,必須保持復(fù)位值。
位15:0 IDRy[15:0]:端口輸入數(shù)據(jù)(Port input data) (y = 0..15)
這些位為只讀形式,只能在字模式下訪問。它們包含相應(yīng)I/O端口的輸入值
GPIO端口輸出數(shù)據(jù)寄存器(GPIOx_ODR) (x = A..I)
偏移地址:0x14
復(fù)位值:0x0000 0000
位31:16保留,必須保持復(fù)位值。
位15:0 ODRy[15:0]:端口輸出數(shù)據(jù)(Port output data) (y = 0..15)
這些位可通過軟件讀取和寫入。
注意:對于原子置位/復(fù)位,通過寫入GPIOx_BSRR寄存器,可分別對ODR位進行置位和復(fù)位(x = A..I/)
別名區(qū)的外設(shè)基地址
PERIPH_BASE = 0X4000 0000
外設(shè)存儲器映射
AHB1PERIPH_BASE =PERIPH_BASE + 0x0002 0000 = 0x4002 0000
AHB1總線的各外設(shè)地址
GPIOA_BASE = AHB1PERIPH_BASE + 0x0000 = 0x4002 0000
GPIOB_BASE = AHB1PERIPH_BASE + 0x0400 = 0x4002 0400
……
GPIOK_BASE = AHB1PERIPH_BASE + 0x2800 = 0x4002 2800
……
IO口的輸出寄存器地址映射
GPIOA_ODR_Addr = GPIOA_BASE + 0X14(十進制是20)= 0x4002 0014
GPIOB_ODR_Addr = GPIOB_BASE + 0X14(十進制是20)= 0x4002 0414
……
GPIOI_ODR_Addr = GPIOI_BASE + 0X14(十進制是20)= 0x4002 2014
IO口的輸入寄存器地址映射
GPIOA_IDR_Addr = GPIOA_BASE + 0X10(十進制是16)=0x4002 0010
GPIOB_IDR_Addr = GPIOB_BASE + 0X10(十進制是16)= 0x4002 0410
……
GPIOI_IDR_Addr = GPIOI_BASE + 0X10(十進制是16)= 0x4002 2010
根據(jù)公式和圖可以計算寄存器位的位帶別名地址:以GPIOA6輸出為例
寄存器地址:0x4002 0014
設(shè)備位帶區(qū)基地址:0x4000 0000
位帶別名區(qū)基地址(已知):0x4200 0000
位帶區(qū)的字節(jié)偏移量:0x4002 0014 - 0x4000 0000 = 0x2 0014
字偏移地址:(0x2 0014×0x20)+(6×4)= 0x40 0298
(0x2 0014×8 + 6)×4 = 0x40 0298
上式中,“4”表示一個字為4個字節(jié),“*8”表示一個字節(jié)中有8個比特。
位帶別名區(qū)地址:0x4200 0000 + 0x40 0298 = 0x4240 0298
熱后用C語言以此地址定義一個指針,用來對GPIOA6進行置位和清除:
#define PoutA(6)*((volatile unsigned long*)0x4240 0298
PoutA(6)=1;//輸出高電平
PoutA(6)=0;//輸出低電平
其他參考資料:
STM32中的SRAM依然是8位的,所以RAM中任一地址對應(yīng)一個字節(jié)內(nèi)容。在位帶區(qū)中,每個比特都映射到別名地址區(qū)的一個字——這是只有LSB有效的字。當一個別名地址被訪問時,會先把該地址變換成位帶地址。對于讀操作,讀取位帶地址中的一個字,再把需要的位右移到LSB,并把LSB返回。對于寫操作,把需要寫的位左移至對應(yīng)的位序號處,然后執(zhí)行一個原子的“讀-改-寫”過程。
位帶區(qū)中的每個比特都映射到別名地址區(qū)的一個字——這是只有LSB有效的字(位帶別名區(qū)的字只有最低位有意義)。
對于SRAM中的某個比特,
該比特在位帶別名區(qū)的地址:AliasAddr =0x22000000 + ((A‐0x20000000)*8+n)*4
= 0x22000000 + (A‐0x20000000)*32 + n*4
對于片上外設(shè)位帶區(qū)的某個比特,
該比特在位帶別名區(qū)的地址:AliasAddr =0x42000000 + ((A‐0x40000000)*8+n)*4
= 0x42000000 + (A‐0x40000000)*32 + n*4