通常来说,GPIO 的工作模式会在初始化时就确定好,但是在芯片工作中偶尔还是会出现需要改变 GPIO 工作模式的情况,比如在没有外接电阻的情况下用软件模拟 I2C,这时候就需要通过寄存器进行操作。
涉及到的寄存器
一组 GPIO 有 16 个 IO 口,每个 IO 口都需要配置输入或输出、具体的输入输出模式,也就需要 4 位二进制,总共需要 64 位二进制,而 STM32 的寄存器为 32 位,所以 GPIO 工作模式的配置寄存器就分成了两个:CRL(GPIOx,x=0~7),CRH(GPIOx,x=8~15)。
其中,每个 GPIO 口对应的 4 位寄存器分为两部分:CNF(高 2 位),MODE(低 2 位)。CNF 对应具体的输入输出模式,MODE 对应输入或输出,如下表所示:
寄存器名 | 配置位含义 |
---|---|
CNF | 输入模式下: 00 模拟输入 01 浮空输入(复位后的状态) 10 上拉/下拉输入 11 保留 输出模式下 00 通用推挽输出 01 通用开漏输出 10 复用推挽输出 11 复用开漏输出 |
MODE | 00 输入模式(复位后的状态) 01 输出模式,最大速度 10MHz 10 输出模式,最大速度 2MHz 11 输出模式,最大速度 50MHz |
怎么操作
假设我想把 PB11 改成浮空输入(改成其他模式以此类推),PB11 是高 8 位的 GPIO,因此这里需要操作 CRH 寄存器。
第一步,清零寄存器位
为了后面方便写入寄存器,要先清空寄存器位。前面说了,每个 GPIO 口对应 4 位寄存器,PB11 是高 8 位 GPIO 中的第4 位,因此需要将 CRH 的 12~15 位清零。代码如下:
GPIOB->CRH &= 0xFFFF0FFF
第二步,写入寄存器
因为是浮空输入,所以 MODE 应该为 00,CNF 应该为 01,拼起来就是[CNF, MODE]=[01,00]=4(十进制)。代码如下:
GPIOB->CRH |= 4<<12
两步合起来,用宏定义表示如下:
#define PB11_IN() {GPIOB->CRH &= 0xFFFF0FFF;GPIOB->CRH |= 4<<12;}