历史上的今天
今天是:2025年03月13日(星期四)
2019年03月13日 | 【STM32】STM32端口复用和重映射(AFIO辅助功能时钟)
2019-03-13 来源:eefocus
STM32F1xx官方资料:
《STM32中文参考手册V10》-第8章通用和复用功能IO(GPIO和AFIO)
端口复用功能
端口复用的定义
STM32有许多的内置外设(如串口、ADC、DCA等等),这些外设的外部引脚都是和GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫复用。详细的可以参考《STM32F103ZET6数据手册》p30的内容,表格的倒数第二栏就表示端口复用功能。
比如说,STM32的串口1的引脚对应的I/O位PA9、PA10。而PA9、PA10默认的功能都是GPIO,所以说当PA9、PA10引脚作为串口1使用的时候就是端口复用。

那么,什么时候端口是默认功能,什么时候端口是复用功能呢?
STM32时钟系统的配置除了初始化的时候在system_stm32f10x.c中的SystemInit函数中外,其他的配置主要在stm32f10x_rcc.c文件中, 所以GPIO等等外设的时钟使能函数都是在此文件中。同时我们通过函数名可以得到规律:GPIOA-GPIOC是挂载在APB2下面,TIM2-TIM4是挂载在APB1下面,DMA是挂载在AHB下面。所以调用函数的名称是需要根据这个来确定的。
端口复用初始化过程
接下来看一下端口复用初始化过程的步骤,拿串口1为例:
1、GPIO端口时钟使能。要使用到端口复用,首先是要使能端口的时钟了;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2、复用的外设时钟使能。比如要将PA9、PA10引脚复用成串口,必须也要使能串口时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3、端口模式配置。在I/O复用位内置外设功能引脚的时候,必须设置GPIO端口的模式。至于在复用功能下,GPIO的模式怎么设置,可以查看手册《STM32中文参考手册》p110的内容。这里拿USART1为例,进行配置,要配置全双工的串口1,TX引脚需要推挽复用输出,RX引脚需要浮空输入或者上拉输入;

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);
总而言之,使用复用功能的时候至少要使能2时钟:GPIO时钟使能、复用的外设时钟使能。同时还要初始化GPIO以及复用外设功能(端口模式配置)。
端口重映射
端口重映射的定义
为了使不同的器件封装的外设I/O功能数量达到最优,可以把一些复用功能重新映射到其他的引脚上。STM32中有许多的内置外设的输入、输出引脚都具有重映射(Remap)的功能。
我们知道,每个内置外设都有若干个输入、输出引脚,一般这些引脚的输出端口都是固定不变的,为了更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口之外,还可以通过设定重映射寄存器的方式把这个外设的引脚映射到其他的端口。
简单讲,就是把引脚的外设功能映射到其他的引脚上,但不是可以随便映射的,具体的对应关系参考《STM32F103ZET6数据手册》p30的内容,表格的最后一栏就表示端口重映射功能。
这里同样用串口1为例来说明。

可以看出,我们可以将串口1重映射到PB6、PB7引脚上。
端口重映射初始化过程
接下来看一下端口重映射初始化过程的步骤,拿串口1为例,除了之前使能复用功能的2个时钟之外,还需要使能AFIO功能时钟,然后调用重映射函数:
1、GPIO端口时钟使能。要使用到端口复用,首先是要使能端口的时钟了;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2、复用的外设时钟使能。比如要将PB6、PB7引脚复用成串口,必须也要使能串口时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3、使能AFIO时钟。重映射必须使能AFIO时钟;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4、开启重映射;
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
这样,就将串口1的TX和RX引脚映射到PB6、PB7引脚上面了。至于哪些功能可以重映射,除了查看中文参考手册之外,还可以从GPIO_PinRemapConfig函数入手查看第一个入口参数的取值范围的值。stm32f10x_gpio.h中定义了一些宏定义的标识符:
#define GPIO_Remap_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */
#define GPIO_Remap_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */
#define GPIO_Remap_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */
#define GPIO_Remap_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */
#define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */
#define GPIO_FullRemap_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */
#define GPIO_PartialRemap_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */
#define GPIO_FullRemap_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */
#define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */
#define GPIO_PartialRemap2_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */
#define GPIO_FullRemap_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */
#define GPIO_PartialRemap_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */
#define GPIO_FullRemap_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */
可以看出,USART1只有一种重映射,而USART3存在部分重映射和完全重映射。所谓部分重映射就是部分引脚和默认的是一样的,完全重映射就是所有引脚都映射到了新的引脚。可以查看《STM32中文参考手册》p119的内容查看部分重映射和完全重映射的内容。而在之前最后开启重映射的函数中,根据第一个参数,来确定是部分重映射还是全部重映射。
AFIO辅助功能时钟
之前在端口重映射的时候,讲到要使能AFIO辅助功能时钟。那么什么时候需要开启(使能)呢?
对寄存器AFIO_MAPR、AFIO_EXTICRx和AFIO_EVCR进行读写操作前,应当首先开启AFIO时钟。
AFIO_MAPR:配置复用功能重映射
AFIO_EXTICRx:配置外部中断线映射
AFIO_EVCR: 配置事件输出
史海拾趣
|
各位大侠, 我最近在做一个报告,要求要用FPGA连接耳麦采取声音信号然后处理 储存。 真是万事开头难啊,刚开始就卡住了 无从下手。 希望大侠们给点建议。多谢了! 有相关研究的同仁们可以加我izhangdan@gmail.com 希望在这方面有所长 ...… 查看全部问答> |
|
写了一个mirror driver, 我想用share memory方式和app通信。 但出了个问题,create sharememory需要app进程的上下文。 我想是用createfile提供,但mirror driver如何提供设备连接名呢? 不知这种方式是否可行,如不行,还有别的办法吗? 还有 ...… 查看全部问答> |
|
为了能捕捉到有程序启动、关闭、激活等消息,我用了以下代码。但这样会存在一个问题,就是打开文件夹时,文件夹里面的内容无法显示。请问是什么原因,或是能用别的什么办法捕捉到程序启动、关闭等消息吗? ...… 查看全部问答> |
|
这个芯片是怎么工作的。 ADC的采样速率怎么确定是多少?固定的吗? 从这个芯片中读取的数据是不是声音信号的ADC转换值,这个芯片可以用来做ADc用吗? … 查看全部问答> |
|
阿牛哥和同事们第三周着力推智能电表和安防矩阵产品方案,看看贸易商和代理商业务运营模式还是有很大区别的。 情报搜集,重点扫荡。中标电表客户还有中标安防监控工程上游制造商机会最大,一一联系。涉及太多商业机密和 ...… 查看全部问答> |
|
在C里我定义数组unsigned int a[5],b[100]和变量unsigned int c 线性汇编子函数要访问a[3]、b、c,会出现下面的警告和错误,困惑...我的线性汇编是参照汇编程序写的。。。 &nb ...… 查看全部问答> |
|
对于开发这些便携式设备的系统和产品设计人员来说,更长的电池寿命是最大挑战之一。 为了帮助解决这一挑战并为设计人员提供显著优势,德州仪器 (TI) 现在推出了两款采用 TI 获得专利的新 MaxLife™ 快速充电技术的电源管理芯片组。 MaxLife 电 ...… 查看全部问答> |
|
如果我让程序在内部的ROM运行一会,比如说从0000H运行到0016H,在这个时候我拉低EA(我把P3.4口的引脚接到了EA引脚上,拉低P3.4相当于拉低EA),这样的话程序会怎么运行?假设拉低EA是单字节指令。运行拉低EA命令后,地址变成0017H,然后程序是不是会 ...… 查看全部问答> |




