欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32端口复用和重映射

程序员文章站 2024-02-25 18:22:15
...

端口复用和重映射都是和单片机的I/O口有关系,端口复用是将一个I/O赋予多个功能,通过设置I/O的工作模式来切换不同的功能。重映射是将某些I/O口上面的功能映射到其他I/O口上面去。但是注意一点:重映射的I/O都是厂家设置好的,不能自己更改。

端口复用

外设

在说端口复用之前先明白一个概念:什么是外设?什么是内置外设?

外部设备简称“外设”,是指连在计算机主机以外的硬件设备。对数据和信息起着传输、转送和存储的作用,是计算机系统中的重要组成部分。
—百度百科

内置外设就是集成在单片机内部的外设,存在对应的寄存器。可参考:单片机里内部外设和外设分别是什么

端口复用

STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。

例如串口1的发送接收引脚是PA9,PA10,当我们把PA9,PA10不用作GPIO,而用做复用功能串口1的发送接收引脚的时候,叫端口复用。

端口复用设置步骤

  1. GPIO时钟使能;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  2. 复用外设时钟使能
    比如你要将端口PA9,PA10复用为串口,所以要使能串口时钟。
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  3. 端口模式配置。 GPIO_Init()函数。

具体说下第3步 端口模式配置,在使用I/O时,首先要进行初始化,

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

第一个参数是哪组I/O口,第二组I/O是一个结构体指针

typedef struct
{
  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */

  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */

  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;

主要看一下 GPIO_Mode 这个参数的取值

typedef enum
{ GPIO_Mode_AIN = 0x0,      //模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,//浮空输入
  GPIO_Mode_IPD = 0x28,//下拉输入 
  GPIO_Mode_IPU = 0x48,//上拉输入
  GPIO_Mode_Out_OD = 0x14,//开漏输出
  GPIO_Mode_Out_PP = 0x10,//推挽输出
  GPIO_Mode_AF_OD = 0x1C,//复用开漏输出
  GPIO_Mode_AF_PP = 0x18//复用推挽输出
}GPIOMode_TypeDef;

stm32端口复用和重映射
在数据手册中可以看到 PA9和PA10可以复用为串口(Default),
stm32端口复用和重映射
从上两张图中可以看出,复用为串口发送需要将 PA9设置为 推挽复用输出,

代码示例:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO时钟使能

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//外设时钟(串口)使能

//初始化IO为对应的模式
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);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  //PA10 PA.10 浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);  

总结

GPIO复用功能就是同样的几个I/O口可以通过设置I/O模式,使能相应时钟, 从而实现不同的功能。具体的设置可以参考 stm32中文参考手册和相应芯片的 dataSheet。

重映射

每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。

重映射技术的需求背景:

  • I/O的复用:GPIO和内置外设共用引出管脚
  • I/O的重映射:复用功能(AFIO)从不同的GPIO管脚引出
  • 方便了PCB的设计,减少了信号交叉干扰
  • 分时复用某些外设,虚拟地增加了端口数目
  • 为了使不同器件封装的外设IO功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。

还是以串口1为例
stm32端口复用和重映射
上图中的,Remap对应的I/O就是可以重映射到的I/O,Default就是该I/O默认可复用的功能。
从上图中可以看出 串口1 可以重映射到 PB6和PB7引脚,也就是说如果PA9和PA10引脚不好用的时候,或者已经被占用了;那么可以用PB6和PB7来实现串口1的功能。

AFIO重映射的操作步骤:

  1. 使能倍重新映射到的I/O端口时钟
  2. 使能被重新映射的外设时钟
  3. 使能AFIO功能的时钟(勿忘)
  4. 进行重映射

注意第三步,使能AFIO功能时钟,为什么需要使能这个时钟 & 什么时候需要使能这个时钟, 可以参见下面这个回答

那么,问题来了!
  AFIO 是什么?AFIO 时钟什么时候需要开启?
  
  我们从《STM32中文参考手册_V10》中找到:对寄存器 AFIO_EVCR、AFIO_MAPR 和 AFIO_EXTICRX 进行读写操作前,应当首先打开 AFIO 的时钟(设置 APB2 外设时钟使能寄存器 RCC_APB2ENR)。
  也就是说:当你需要配置 AFIO 这些寄存器的时候,就需要把 RCC_APB2ENR 寄存器的 AFIO 位置‘1’打开 AFIO 时钟。
  
  跟 AFIO 相关的寄存器有:
  1、 事件控制寄存器(AFIO_EVCR)
  2、 复用重映射和调试I/O 配置寄存器(AFIO_MAPR)
  3、 外部中断配置寄存器1(AFIO_EXTICR1)
  4、 外部中断配置寄存器2(AFIO_EXTICR2)
  5、 外部中断配置寄存器3(AFIO_EXTICR3)
  6、 外部中断配置寄存器4(AFIO_EXTICR4)
  看看这些寄存器的定义,我们就明白,这些寄存器是用于“事件控制”、“重映射”、“调试IO配置”、“外部中断”的。例如 AFIO_EXTICRX 用于选择 EXTIx 外部中断的输入源。
  总结:当我们需要配置这些 AFIO 寄存器的时候,就需要打开 RCC_APB2ENR 寄存器的 AFIO 时钟,而不是用到引脚复用功能的时候打开。
  ——-来自于: STM32的AFIO时钟什么时候需要开启

部分重映射 & 完全重映射

  • 部分重映射:功能外设的部分引脚重新映射,还有一部分引脚是原来的默认引脚。
  • 完全重映射:功能外设的所有引脚都重新映射。
    stm32端口复用和重映射
    如何配置部分重映射 & 完全重映射在后面

引脚重映射配置过程(串口3为例):
1. 使能GPIO时钟(重映射后的IO);
2. 使能功能外设时钟(例如串口3);
3. 使能AFIO时钟。重映射必须使能AFIO时钟:
4. 开启重映射。

  GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);
  //根据第一个参数,来确定是部分重映射还是全部重映射

stm32端口复用和重映射
查看第一个参数的取值,如下图:
stm32端口复用和重映射
以串口3为例,如果想部分映射:GPIO_PinRemapConfig()的第一个参数取值应该是:上图红框框里面的第一个参数,即 GPIO_PartialRemap_USART3,如果是完全映射就是:GPIO_FullRemap_USART3

总结

重映射就是将在某个I/O实现的功能映射到另外的I/O口, 主要是为了布线的方便以及信号的干扰。具体配置步骤与部分重映射 & 完全重映射前面都已说明。

参考资料

正点原子视频
STM32中GPIO的8种工作模式
STM32的AFIO时钟什么时候需要开启
单片机里内部外设和外设分别是什么