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