本人邮箱
:[email protected],欢迎交流讨论。
欢迎转载,转载请注明网址:https://blog.csdn.net/qq_43660925/article/details/120684835
一、STM32单片机的IO口结构
二、GPIO的8种工作模式详解
三、GPIO寄存器控制
四、端口初始化
五、端口复用
六、端口重映射
STM32单片机的IO口与51单片机相比较为复杂,使用前必须操作相关寄存器完成对IO口的初始化配置(单片机内部会选择不同的硬件电路连接)。IO口一共是8种模式,分别为4输入 + 2 输出 + 2 复用输出,以下是八种模式的概念和工作原理:
1、基本概念
GPIO八大模式 | ||
输入摸式 | 模拟输入Analog | 将模拟信号转换为数字信号 |
浮空输入Input floating | 浮空模式默认电平是不确定的,完全由外部输入决定检测按键是否按下,就是配置为该模式 | |
下拉输入Input pull down | 上拉和下拉输入默认电平由上拉和下拉电阻决定,上拉即将不确定电平通过一个电阻钳为在高电平,下拉同理 | |
上拉输入Input pull up | ||
输出模式 | 开漏输出Output open drain | 若不外接电路,输出一直为低电平,要想得到高电平状态,需要外接上拉电阻 |
推挽输出Output push pull | 可直接输出高低电平,直接驱动功耗不高的电子器件 | |
复用模式 | 复用开漏输出Alternate Function open drain | 引脚第二功能配置 |
复用推挽输出Alternate Function push pull | 引脚第二功能配置 | |
开漏输出和推挽输出的区别
推挽输出 | 开漏输出 | |
---|---|---|
高电平驱动能力 | 强 | 由外部上拉电阻提供 |
低电平驱动能力 | 强 | 强 |
电平跳转速度 | 快 | 由外部上拉电阻决定电阻越小,反应越快,功耗越大 |
线与功能 | 不支持 | 支持 |
电平转换 | 不支持 | 支持 |
STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:
2 | 32位配置寄存器 | (GPIOx_CRL,GPIOx_CRH) |
---|---|---|
2 | 32位数据寄存器 | (GPIOx_IDR和GPIOx_ODR) |
1 | 32位置位/复位寄存器 | GPIOx_BSRR |
1 | 16位复位寄存器 | GPIOx_BRR |
1 | 32位锁定寄存器( | GPIOx_LCKR |
根据数据手册中列出的每个I/O端口的特定硬件特征, GPIO端口的每个位可以由软件分别配置成多种模式。大家如果想要了解每个寄存器的详细使用方法,可以参考《STM32 中文参考手册 V10》P105~P129
。这边仅介绍GPIO口的初始化用到的寄存器
CRL 和 CRH 控制着每个 IO 口的模式及输出速率。
接下来我们看看端口低配置寄存器 CRL 的描述
从上图还可以得出:STM32 的 CRL 控制着每组 IO 端口(A~G)的低 8 位的模式。而高 8位输出口由CRH 控制,作用完全一样,这里不介绍,每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,低两位为 MODE。比如 0X3 表示推挽输出模式(做输出口用,50M 速率)、0XB 表示复用输出(使用 IO 口的第二功能,50M 速率)。
下面我们讲解一下怎样通过固件库设置 GPIO的相关参数和输出
在固件库开发中,操作寄存器 CRH 和 CRL 来配置 IO 口的模式和速度是通过文件STM32f10x_gpio.h
中GPIO 初始化函数完成
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
这个函数有两个参数,第一个参数
是用来指定 GPIO,取值范围为 GPIOA~GPIOG。
第二个参数
为初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。下面我们看看这个结构体的定义:
typedefstruct
{ uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
下面我们通过一个 GPIO 初始化实例来讲解这个结构体的成员变量的含义。
通过初始化结构体初始化 GPIO 的常用格式是:
GPIO_InitTypeDef GPIO_InitStructure;//定义一个该结构体类型变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // PC.13 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz
GPIO_Init(GPIOC, &GPIO_InitStructure);//根据设定参数配置 GPIO
上面代码的意思是设置 GPIOC 的第 13 个端口为推挽输出模式,同时速度为 50M。从上面初始化代码可以看出,结构体 GPIO_InitStructure 的第一个成员变量 GPIO_Pin 用来设置是要初始化哪个或者哪些 IO 口;第二个成员变量 GPIO_Mode 是用来设置对应 IO 端口的输出输入模式(8种),第三个参数是 IO 口速度设置(三个可选值)
总结:
叶柄 GPIO_InitTypeDef 引出叶片GPIO_InitStructure
叶片配置 GPIO_InitStructure
生长在树干GPIO_Init()函数中
STM32 有很多的内置外设,这些外设的外部引脚都是与 GPIO 复用的。简单来说就是作为第二功能
,当作第二功能时就叫做复用。这部分知识在《STM32 中文参考手册 V10》的 P109,P116~P121 有详细的讲解哪些GPIO 管脚是可以复用为哪些内置外设的。这里我们就不一一讲解。这里以串口为例
比如说 STM32F103C8T6 有串口1,我们可以查手册知道,PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。串口 1 复用管脚如下表
复用端口初始化步骤:
1) GPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2) 复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3) 端口模式配置即端口初始化。 在 IO 复用位内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》P110 的表格“8.1.11 外设的 GPIO 配置
”。这里我们拿 Usart1 举例:
串口复用 GPIO 配置从以上表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出,RX 管脚配置为浮空输入或者带上拉输入。
//USART1_TX PA.9 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX PA.10 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
上面代码的含义在我们的做第一个点亮LED实验之后大家自然会了解
总结:我们在使用复用功能的是时候,最少要使能 2 个时钟:
1) GPIO 时钟使能
2) 复用的外设时钟使能
同时要初始化 GPIO 以及复用外设功能(AF)
为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。简单来说就是将某引脚第二功能也赐予其他的引脚,但不是随随便便赐予(映射),具体对应关系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置
”有讲解。这里同样拿串口 1 为例来讲解。
从表中可以看出,默认情况下,串口 1 复用的时候
的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。
所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后
要调用重映射函数。详细步骤为:
1)使能 GPIOB 时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
2)使能串口 1 时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3)使能 AFIO 时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4)开启重映射:
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。至于有哪些功能可以重映射,大家除了查看中文参考手册之外,还可以从在 stm32f10x_gpio.h 文件中GPIO_PinRemapConfig 函数入手查看第一个入口参数
的取值范围可以得知。
注意
:
串口中 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重映射就是所有管脚都重新映射到其他管脚。自行查看手册中的 USART3 重映射表,这里只是对重映射概念做个简要的描述
总结:我们在使用重映射功能的是时候,就最少要使能 3个时钟:
1)复用所需时钟
2)重映射时钟
同时要初始化 GPIO 并开启映射
跳转开头