一、GPIO原理
首先要提一下,在固件库中,GPIO 端口操作对应的库函数函数以及相关定义在文件
stm32f10x_gpio.h 和 stm32f10x_gpio.c 中。STM32 的 IO 口相比 51 而言要复杂得多,所以使用起来也困难很多。首先 STM32 的 IO 口可以由软件配置成如下 8 种模式:
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏复用功能
每个 IO 口可以自由编程,但 IO 口寄存器必须要按 32 位字被访问。STM32 的很多 IO 口都是 5V 兼容的,这些 IO 口在与 5V 电平的外设连接的时候很有优势,具体哪些 IO 口是 5V 兼容的,可以从该芯片的数据手册管脚描述章节查到(I/O Level 标 FT 的就是 5V 电平兼容的)。STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:配置模式的 2 个 32 位的端口配置寄存器 CRL 和 CRH;2 个 32 位的数据寄存器 IDR 和 ODR;1 个 32 位的置位/复位寄存器BSRR;一个 16 位的复位寄存器 BRR;1 个 32 位的锁存寄存器 LCKR。CRL 和 CRH 控制着每个 IO 口的模式及输出速率。大家如果想要了解每个寄存器的详细使用方法,可以参考《STM32 中文参考手册 》。
表1 端口位配置表
表2 输出模式配置表
一般通用I/O分组是从GPIOA~GPIOG(具体有多少组和板子的IO口数量有关),每个GPI/O端口有:两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。这些寄存器在库函数中都是配置好的,我们只需要对应上面的表格中按模式调用即可。
其中STM32 的 CRL 控制着每组 IO 端口(A~G)的低 8 位的模式。每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。这里我们可以记住几个常用的配置,比如 0X0 表示模拟输入模式(ADC 用)、0X3 表示推挽输出模式(做输出口用,50M 速率)、0X8 表示上/下拉输入模式(做输入口用)、0XB 表示复用输出(使用 IO 口的第二功能,50M 速率)。CRH 的作用和 CRL 完全一样,只是 CRL 控制的是低 8 位输出口,而 CRH 控制的是高 8位输出口。
二、实例分析
接下来我们讲讲GPIO初始化的代码
每个GPIO使用前都必须进行时钟使能,(不管是通用IO还是复用为其他功能,都必须按照IO使用的时钟进行初始化,关于时钟是比较复杂但是非常重要,之后在进行串口通信实验时我会给大家做个详细总结。)
1. GPIO时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);//使能GPIOB和GPIOE的时钟,必定的操作
2. GPIO初始化函数
GPIO 相关的函数和定义分布在固件库文件 stm32f10x_gpio.c 和头文件 stm32f10x_gpio.h 文件中。在固件库开发中,操作寄存器 CRH 和 CRL 来配置 IO 口的模式和速度是通过 GPIO 初始化函数完成:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
这个函数有两个参数,第一个参数是用来指定 GPIO组别,取值范围为 GPIOA~GPIOG。
第二个参数为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。
typedef struct
{ uint16_t GPIO_Pin; //IO口的引脚
GPIOSpeed_TypeDef GPIO_Speed; //IO工作频率
GPIOMode_TypeDef GPIO_Mode; //IO口的工作模式
}GPIO_InitTypeDef;
这些初始化函数和结构体已经在库函数stm32f10x_gpio.c 和头文件 stm32f10x_gpio.h中由系统定义好,我们只需在主函数中调用即可。下面是初始化PB5引脚作为输出的例子。
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);//使能GPIOB和GPIOE的时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//初始化IO口模式为推挽输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//输出的引脚PB5
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;//输出速度50MHZ
GPIO_Init(GPIOB,&GPIO_InitStructure);//调用GPIO初始化函数,配置PB5
GPIO_SetBits(GPIOB,GPIO_Pin_5);//设置端口位 PB5输出1
}
这样PB5的初始化就完成了,其他IO口也是用同样的方式进行初始化。以上的GPIO结构体中对应的成员类型都可以在stm32f10x_gpio.h中找到,可以根据自己的需求初始化GPIO。