1 GPIO功能描述
1.1 每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL, GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。
根据数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置成多种模式。
─ 输入浮空
─ 输入上拉
─ 输入下拉
─ 模拟输入
─ 开漏输出
─ 推挽式输出
─ 推挽式复用功能
─ 开漏复用功能
每个I/O端口位可以自由编程,然而必须按照32位字访问I/O端口寄存器(不允许半字或字节访问)。 GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器进行读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会发生危险。
下图给出了一个I/O端口位的基本结构
Vdd_ft,部分io口可以容忍5V
1.2 端口位配置表
- 通用推挽输出模式(00):在这种模式下,N-MOS 管和 P-MOS 管都会工作。当控制输出为低电平时,P-MOS 管关闭,N-MOS 管导通,使输出低电平;当控制输出为高电平时,P-MOS 管导通,N-MOS 管关闭,使输出高电平。I/O 端口的电平就是输出的电平。外部上拉和下拉的作用是控制在没有输出时 I/O 口的电平。此模式可以输出强高电平和强低电平,适用于连接数字器件。推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。
- 通用开漏输出模式(01):在开漏输出模式时,只有 N-MOS 管工作。如果控制输出为低电平,则 P-MOS 管关闭,N-MOS 管导通,使输出低电平;若控制输出为高电平,则 P-MOS 管和 N-MOS 管都关闭,输出指令不起作用,此时 I/O 端口的电平不由输出的高电平决定,而是由 I/O 端口外部的上拉或者下拉决定(如果没有上拉或者下拉,I/O 口就处于悬空状态)。并且施密特触发器是打开的,即输入可用,通过输入数据寄存器可读取 I/O 的实际状态,I/O 口的电平不一定是输出的电平。开漏输出模式适合用于电平不匹配的场合,要得到高电平需要接上拉电阻,其吸收电流的能力相对较强(一般 20mA 以内)。它的一个特点是可以通过改变上拉电源的电压来改变传输电平,还可以将多个开漏输出的 Pin 连接到一条线上,通过一只上拉电阻,在不增加任何器件的情况下,形成“与逻辑”关系。
- 复用功能推挽输出模式(10):当 GPIO 复用为其他外设(如 I2C)时,输出数据寄存器无效,输出的高低电平来源于其他外设。施密特触发器打开,输入可用,通过输入数据寄存器可获取 I/O 实际状态。除了输出信号的来源改变,其他与通用推挽输出模式相同。
- 复用功能开漏输出模式(11):当 GPIO 复用为其他外设时,输出数据寄存器也无效,输出的高低电平同样来源于其他外设。施密特触发器打开,输入可用,通过输入数据寄存器可读取 I/O 实际状态。除了输出信号的来源改变,其他与通用开漏输出模式相同。
在实际使用中,可以根据具体的需求来选择合适的输出模式。例如,如果需要输出强高低电平并连接数字器件,可选择通用推挽输出模式;如果要连接不同电平的器件或实现特定的电平转换,通用开漏输出模式可能更合适;而当 GPIO 被用作其他外设功能时,则需根据外设的要求选择复用功能推挽输出模式或复用功能开漏输出模式。同时,在使用开漏输出模式时,通常需要接上拉电阻以确保能输出高电平。
1.3 输出模式位
1.4 复用功能(AF)
使用默认复用功能前必须对端口位配置寄存器编程。
● 对于复用的输入功能,端口必须配置成输入模式(浮空、上拉或下拉)且输入引脚必须由外部
驱动。
注意: 也可以通过软件来模拟复用功能输入引脚,这种模拟可以通过对GPIO控制器编程来实现。此时,端口应当被设置为复用功能输出模式。显然,这时相应的引脚不再由外部驱动,而是通过GPIO控制器由软件来驱动。
● 对于复用输出功能,端口必须配置成复用功能输出模式(推挽或开漏)。
● 对于双向复用功能,端口位必须配置复用功能输出模式(推挽或开漏)。这时,输入驱动器被
配置成浮空输入模式。
如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。如果软件把一个GPIO脚配置成复用输出功能,但是外设没有被激活,它的输出将不确定。
2 GPIO寄存器描述
2.1 调用GPIO初始化函数,就可以直接初始化成为默认值
2.2 两个32位配置寄存器(GPIOx_CRL, GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。
1.端口配置低寄存器(GPIOx_CRL) (x=A..E)可读可写
2.端口配置高寄存器(GPIOx_CRH) (x=A..E)
3.端口输入数据寄存器(GPIOx_IDR) (x=A..E)
4.端口输出数据寄存器(GPIOx_ODR) (x=A..E)
5.端口位设置/清除寄存器(GPIOx_BSRR) (x=A..E) 6.端口位清除寄存器(GPIOx_BRR) (x=A..E)
7. 端口配置锁定寄存器(GPIOx_LCKR) (x=A..E)
当执行正确的写序列设置了位16(LCKK)时,该寄存器用来锁定端口位的配置。位[15:0]用于锁定GPIO端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了LOCK序列后,在下次系统复位之前将不能再更改端口位的配置。
每个锁定位锁定控制寄存器(CRL, CRH)中相应的4个位。
3 寄存器映射
3.1寄存器是特殊的存储器,给寄存器地址命名的过程,就叫做寄存器映射
3.2 寄存器解读
- 寄存器名字
- 偏移量及复位值
- 寄存器位表
- 位功能描述
3.3 寄存器映射举例
3.4 寄存器地址计算
为了方便编写代码及使用,我们将寄存器地址分为三个部分:
1、总线基地址(BUS_BASE_ADDR)
2、外设基于总线基地址的偏移量(PERIPH_OFFSET)
3、寄存器相对外设基地址的偏移量(REG_OFFSET)
寄存器地址= BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
3.5 总线基地址
3.6 GPIO外设基地址及偏移量
所属总线 | 外设 | 基地址 | 偏移量 |
APB2 0X4001 0000 | GPIOA | 0X4001 0800 | 0X8000 |
GPIOB | 0X4001 0C00 | 0XC000 | |
GPIOC | 0X4001 1000 | 0X1000 | |
GPIOD | 0X4001 1400 | 0x1400 | |
GPIOE | 0X4001 1800 | 0x1800 | |
GPIOF | 0X4001 1C00 | 0X1C00 | |
GPIOG | 0X4001 2000 | 0x2000 |
此表的偏移量:是相对APB2外设的基地址(APB2PERIPH_BASE)来说
3.7 GPIO寄存器地址及偏移量
所属总线 | 所属外设 | 寄存器 | 地址 | 偏移量 |
APB2 0X4001 0000 | GPIOA 0X4001 0800 (外设基地址) | GPIOA_CRL | 0X4001 0800 | 0X00 |
GPIOA _CRH | 0X4001 0804 | 0X04 | ||
IGPIOA_IDR | 0X4001 0808 | 0X08 | ||
GPIOA_ODR | 0X4001 080C | 0X0C | ||
GPIOA_IDR | 0X4001 0810 | 0X10 | ||
GPIOA_BRR | 0X4001 0814 | 0X14 | ||
GPIOA_LCKR | 0X4001 0818 | 0X18 |
寄存器是32位,32位就是4Byte,所以隔着4
3.8 GPIOA ODR寄存器地址计算过程:
1,获取外设挂在哪个总线上面?查:系统结构图
2,获取总线基地址,APB2总线基地址:0X4001 0000
3,获取外设地址偏移量,GPIOA相对APB2总线偏移量是:0X800
4,获取寄存器地址偏移量,ODR相对GPIOA外设基地址的偏移量是:0x011
寄存器地址= BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
GPIOA_ODR =0X4001 0000 +0X800 + 0X0C = 0X4001 0800C
这就得到了这个寄存器地址了
3.9 使用结构体,可以很方便的完成对寄存器的映射:
结构体指针强转
&GPIOA->CRL: 0X4001 0800
&GPIOA->CRH: 0X4001 0804
&GPIOA->IDR: 0X4001 0808
&GPIOA->ODR: 0X4001 080C
依次4个字节