每个通用 I/O 端口包括 4 个 32 位配置寄存器(GPIOx_MODER、 GPIOx_OTYPER、
GPIOx_OSPEEDR 和 GPIOx_PUPDR)、 2 个 32 位数据寄存器(GPIOx_IDR 和
GPIOx_ODR)、 1 个 32 位置位/复位寄存器 (GPIOx_BSRR)、 1 个 32 位锁定寄存器
(GPIOx_LCKR) 和 2 个 32 位复用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)
GPIO主要特性:
输出状态:推挽或开漏+上拉/下拉
从输出数据寄存器(GPIOx_ODR)或外设(复用功能输出)输出数据
可为每个IO选择不同的速度
输入状态:浮空、上拉、下拉、模拟
将数据输入到输入数据寄存器(GPIOx_IDR)或外设(复用功能输入)
置位和复位寄存器(GPIOx_BSRR),对GPIOx_ODR具有按位写权限
锁定机制(GPIOx_LCKR),可冻结IO配置
模拟功能
复用功能输入/输出选择寄存器(一个IO最多可以具有16个复用功能)
快读翻转,每次翻转最快只需要两个时钟周期
引用复用非常灵活,允许将IO引脚用作GPIO或多种外设功能中的一种
注意:在复位期间及复位刚刚完成后,复用功能尚未激活,IO端口被配置为输入浮空模式。复位后,调试引脚处于复用功能的上拉/下拉状态。
● PA15:JTDI 处于上拉状态
● PA14:JTCK/SWCLK 处于下拉状态
● PA13:JTMS/SWDAT 处于下拉状态
● PB4:NJTRST 处于上拉状态
● PB3:JTDO 处于浮空状态
当引脚配置为输出后,写入到输出数据寄存器 (GPIOx_ODR) 的值将在 I/O 引脚上输出。可以在推挽模式下或开漏模式下使用输出驱动器(输出 0 时仅激活 N-MOS)。
输入数据寄存器 (GPIOx_IDR) 每隔 1 个 AHB1 时钟周期捕获一次 I/O 引脚的数据。
所有 GPIO 引脚都具有内部弱上拉及下拉电阻,可根据 GPIOx_PUPDR 寄存器中的值来打开/关闭。
I/O 引脚复用器和映射
微控制器 I/O 引脚通过一个复用器连接到板载外设/模块,该复用器一次仅允许一个外设的复
用功能 (AF) 连接到 I/O 引脚。这可以确保共用同一个 I/O 引脚的外设之间不会发生冲突。
每个 I/O 引脚都有一个复用器,该复用器采用 16 路复用功能输入(AF0 到 AF15) ,可通过
GPIOx_AFRL(针对引脚 0 到 7)和 GPIOx_AFRH(针对引脚 8 到 15)寄存器对这些输入
进行配置:
● 完成复位后,所有 I/O 都会连接到系统的复用功能 0 (AF0)。
● 外设的复用功能映射到 AF1 至 AF13。
● Cortex™-M4F EVENTOUT 映射到 AF15 。
要将 I/O 配制成所需功能,请按照以下步骤操作:
1. 系统功能
将 I/O 连接到 AF0,然后根据所用功能进行配置:
— JTAG/SWD:在各器件复位后,会将这些引脚指定为专用引脚,可供片上调试模块
立即使用(不受 GPIO 控制器控制)。
— RTC_REFIN:此引脚应配置为输入浮空模式。
— MCO1 和 MCO2:这些引脚必须配置为复用功能模式。
可禁止部分或全部 JTAG/SWD 引脚,以释放相关联的引脚供 GPIO 使用
2. GPIO
在 GPIOx_MODER 寄存器中将所需 I/O 配置为输出或输入。
3. 外设复用功能
对于 ADC 和 DAC,在 GPIOx_MODER 寄存器中将所需 I/O 配置为模拟通道。
对于其它外设:
— 在 GPIOx_MODER 寄存器中将所需 I/O 配置为复用功能
— 通过 GPIOx_OTYPER、 GPIOx_PUPDR 和 GPIOx_OSPEEDER 寄存器,分别选
择类型、上拉/下拉以及输出速度
— 在 GPIOx_AFRL 或 GPIOx_AFRH 寄存器中,将 I/O 连接到所需 AFx
4.EVENTOUT
配置用于输出 Cortex™-M4F EVENTOUT 信号的 I/O 引脚(通过将其连接到 AF15)
I/O 端口控制寄存器
每个 GPIO 有 4 个 32 位存储器映射的控制寄存器(GPIOx_MODER、 GPIOx_OTYPER、
GPIOx_OSPEEDR、 GPIOx_PUPDR),可配置多达 16 个 I/O。GPIOx_MODER 寄存器用于
选择 I/O 方向(输入、输出、 AF、模拟)。GPIOx_OTYPER 和 GPIOx_OSPEEDR 寄存器分
别用于选择输出类型(推挽或开漏)和速度 (无论采用哪种 I/O 方向,都会直接将 I/O 速度引
脚连接到相应的 GPIOx_OSPEEDR 寄存器位)。无论采用哪种 I/O 方向, GPIOx_PUPDR 寄
存器都用于选择上拉/下拉。
I/O 端口数据寄存器
每个 GPIO 都具有 2 个 16 位数据寄存器:输入和输出数据寄存器(GPIOx_IDR 和
GPIOx_ODR)。GPIOx_ODR 用于存储待输出数据,可对其进行读/写访问。通过 I/O 输入
的数据存储到输入数据寄存器 (GPIOx_IDR) 中,它是一个只读寄存器。
I/O 复用功能输入/输出
有两个寄存器可用来从每个 I/O 可用的 16 个复用功能输入/输出中进行选择。借助这些寄存
器,可根据应用程序的要求将某个复用功能连接到其它某个引脚。
这意味着可使用 GPIOx_AFRL 和 GPIOx_AFRH 复用功能寄存器在每个 GPIO 上复用多个可
用的外设功能。这样一来,应用程序可为每个 I/O 选择任何一个可用功能。由于 AF 选择信
号由复用功能输入和复用功能输出共用,所以只需为每个 I/O 的复用功能输入/输出选择一个
通道即可。
输入配置
对 I/O 端口进行编程作为输入时:
● 输出缓冲器被关闭
● 施密特触发器输入被打开
● 根据 GPIOx_PUPDR 寄存器中的值决定是否打开上拉和下拉电阻
● 输入数据寄存器每隔 1 个 AHB1 时钟周期对 I/O 引脚上的数据进行一次采样
● 对输入数据寄存器的读访问可获取 I/O 状态
输出配置
对 I/O 端口进行编程作为输出时:
● 输出缓冲器被打开:
— 开漏模式:输出寄存器中的“0”可激活 N-MOS,而输出寄存器中的“1”会使端
口保持高组态 (Hi-Z)(P-MOS 始终不激活)。
— 推挽模式:输出寄存器中的“0”可激活 N-MOS,而输出寄存器中的“1”可激活
P-MOS。
● 施密特触发器输入被打开
● 根据 GPIOx_PUPDR 寄存器中的值决定是否打开弱上拉电阻和下拉电阻
● 输入数据寄存器每隔 1 个 AHB1 时钟周期对 I/O 引脚上的数据进行一次采样
● 对输入数据寄存器的读访问可获取 I/O 状态
● 对输出数据寄存器的读访问可获取最后的写入值
复用功能配置
对 I/O 端口进行编程作为复用功能时:
● 可将输出缓冲器配置为开漏或推挽
● 输出缓冲器由来自外设的信号驱动(发送器使能和数据)
● 施密特触发器输入被打开
● 根据 GPIOx_PUPDR 寄存器中的值决定是否打开弱上拉电阻和下拉电阻
● 输入数据寄存器每隔 1 个 AHB1 时钟周期对 I/O 引脚上的数据进行一次采样
● 对输入数据寄存器的读访问可获取 I/O 状态
模拟配置
对 I/O 端口进行编程作为模拟配置时:
● 输出缓冲器被禁止。
● 施密特触发器输入停用, I/O 引脚的每个模拟输入的功耗变为零。施密特触发器的输出被
强制处理为恒定值 (0)。
● 弱上拉和下拉电阻被关闭。
● 对输入数据寄存器的读访问值为“0”。
将 OSC32_IN/OSC32_OUT 引脚用作 GPIO PC14/PC15 端口引脚
当 LSE 振荡器处于关闭状态时,可分别将 LSE 振荡器引脚 OSC32_IN 和 OSC32_OUT 用
作通用 PC14 I/O 和 PC15 I/O。当 LSE 振荡器处于开启状态时, PC14 I/O 和 PC15 I/O 只能
被配置为 LSE 振荡器引脚 OSC32_IN 和 OSC32_OUT。可通过在 RCC_BDCR 寄存器中将
LSEON 位置 1 来完成此操作。LSE 的优先级高于 GPIO 功能。
注意:当 1.2 V 域掉电时(因器件进入待机模式),或者当备份域由 VBAT 供电时(VDD 不再供电),PC14/PC15 GPIO 功能将丢失。在此情况下, I/O 被设置为模拟输入模式。
将 OSC_IN/OSC_OUT 引脚用作 GPIO PH0/PH1 端口引脚
当 HSE 振荡器处于关闭状态时,可分别将 HSE 振荡器引脚 OSC_IN 和 OSC_OUT 用作通
用 PH0 I/O 和 PH1 I/O。(完成复位后, HSE 振荡器处于关闭状态)。当 HSE 振荡器处于
开启状态时, PH0/PH1 I/O 只能被配置为 OSC_IN/OSC_OUT HSE 振荡器引脚。可通过在
RCC_CR 寄存器中将 HSEON 位置 1 来完成此操作。HSE 的优先级高于 GPIO 功能。
GPIO配置方法:
第一步,使能IO口时钟,配置相关寄存器RCC->AHB1ENR
第二步,初始化IO口模式,配置四个配置寄存器
GPIOx_MODER/GPIOx_OTYPER/GPIOx_OSPEEDR/GPIOx_PUPDR
第三步,操作IO口,输入高低电平,配置寄存器GPIOx_ODR或者BSRRL/BSRRH。
//GPIO复用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0~15,代表IO引脚编号.
//AFx:0~15,代表AF0~AF15.
void GPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8 AFx)
{
GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4));
GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4);
}
//GPIO通用设置
//GPIOx:GPIOA~GPIOI.
//BITx:0X0000~0XFFFF,位设置,每个位代表一个IO,第0位代表Px0,第1位代表Px1,依次类推.比如0X0101,代表同时设置Px0和Px8.
//MODE:0~3;模式选择,0,输入(系统复位默认状态);1,普通输出;2,复用功能;3,模拟输入.
//OTYPE:0/1;输出类型选择,0,推挽输出;1,开漏输出.
//OSPEED:0~3;输出速度设置,0,2Mhz;1,25Mhz;2,50Mhz;3,100Mh.
//PUPD:0~3:上下拉设置,0,不带上下拉;1,上拉;2,下拉;3,保留.
//注意:在输入模式(普通输入/模拟输入)下,OTYPE和OSPEED参数无效!!
void GPIO_Set(GPIO_TypeDef* GPIOx,u32 BITx,u32 MODE,u32 OTYPE,u32 OSPEED,u32 PUPD)
{
u32 pinpos=0,pos=0,curpin=0;
for(pinpos=0;pinpos<16;pinpos++)
{
pos=1<<pinpos; //一个个位检查
curpin=BITx&pos;//检查引脚是否要设置
if(curpin==pos) //需要设置
{
GPIOx->MODER&=~(3<<(pinpos*2)); //先清除原来的设置
GPIOx->MODER|=MODE<<(pinpos*2); //设置新的模式
if((MODE==0X01)||(MODE==0X02)) //如果是输出模式/复用功能模式
{
GPIOx->OSPEEDR&=~(3<<(pinpos*2)); //清除原来的设置
GPIOx->OSPEEDR|=(OSPEED<<(pinpos*2));//设置新的速度值
GPIOx->OTYPER&=~(1<<pinpos) ; //清除原来的设置
GPIOx->OTYPER|=OTYPE<<pinpos; //设置新的输出模式
}
GPIOx->PUPDR&=~(3<<(pinpos*2)); //先清除原来的设置
GPIOx->PUPDR|=PUPD<<(pinpos*2); //设置新的上下拉
}
}
}