Chapter 13 GPIO——位带操作

Chapter 13 GPIO——位带操作

位带简介

STM32 中,两个地方实现了位带,

  • SRAM 区的最低 1MB 空间
  • 外设区的最低 1MB 空间

外设位带区

1
2
3
4
5
6
// 外设位带区的地址为:
0x40000000 ~ 0x40100000 // 大小为 1MB
// 膨胀后的位带别名区地址为:
0x42000000 ~ 0x43FFFFFF
// F103 中所有的所上外设寄存器地址为:
0x40000000 ~ 0x40029FFF

SRAM 位带区

1
2
3
4
// SRAM 位带区地址为:
0x20000000 ~ 0x20100000 // 大小为 1MB
// 膨胀后的位带别名区地址为:
0x22000000 ~ 0x23FFFFFF

位带区和位带别名区的地址转换

1、外设位带别名区地址

对于片上外设位带区的某个位,记它所有字节的地址为 A,位序号为 n =[0, 7],则该位在别名区的地址为:

1
AliasAddr = 0x42000000 + (A - 0x40000000)*8*4 + n*4

2、SRAM 位带别名区地址

1
AliasAddr = 0x22000000 + (A - 0x20000000)*8*4 + n*4

3、统一公式

1
2
3
// 位带地址: addr
// 位序号: bitnum
AliasAddr = (addr & 0xF0000000) + 0x02000000 + ((addr & 0x00FFFFFF)<<5) + (bitnum<<2)
1
2
// 把 “位带地址“ + ”位序号” 转换成位带别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x02000000 + ((addr & 0x00FFFFFF)<<5) + (bitnum<<2))

4、通过指针的形式操作这些位带别名区地址,最终实现位带区的操作

1
2
3
4
// 把一个地址轮换成一个指针
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
// 把位带别名区地址转换成指针
#define BIT_ADDR(addr, bitnum) MEM_ADDR( BITBAND(addr, bitnum) )

GPIO 位带操作

演示 GPIO 中的 ODR 和 IDR 这两个寄存器的位操作

ODR 和 IDR 这两个寄存器对应的 GPIO 基地址偏移是 12 和 8

1、GPIO 寄存器映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// GPIO ODR 寄存器映射
#define GPIOA_ODR_Addr (GPIOA_BASE + 12) // 0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE + 12)
#define GPIOC_ODR_Addr (GPIOC_BASE + 12)
#define GPIOD_ODR_Addr (GPIOD_BASE + 12)
#define GPIOE_ODR_Addr (GPIOE_BASE + 12)
#define GPIOF_ODR_Addr (GPIOF_BASE + 12)
#define GPIOG_ODR_Addr (GPIOG_BASE + 12)

// GPIO IDR 寄存器映射
#define GPIOA_IDR_Addr (GPIOA_BASE + 8) // 0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE + 8)
#define GPIOC_IDR_Addr (GPIOC_BASE + 8)
#define GPIOD_IDR_Addr (GPIOD_BASE + 8)
#define GPIOE_IDR_Addr (GPIOE_BASE + 8)
#define GPIOF_IDR_Addr (GPIOF_BASE + 8)
#define GPIOG_IDR_Addr (GPIOG_BASE + 8)

2、GPIO 位操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 单独操作 GPIO 的某一个 I/O 口,n (0~16)
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr, n)
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr, n)

#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr, n)
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr, n)

#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr, n)
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr, n)

#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr, n)
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr, n)

#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr, n)
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr, n)

#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr, n)
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr, n)

#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr, n)
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr, n)

#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr, n)
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr, n)

3、main 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @brief Main function
* @param none
* @return none
*/
int main(void)
{
// System clock has been set to 72MHz
LED_GPIO_Config();

while(1)
{
//PA5 = 1, Turn on green LED
PAout(5) = 1; // Use Bit-band to set I/O.
SOFT_DELAY;

PAout(5) = 0;
SOFT_DELAY;
}
}