复用与重映射
在芯片原理图上经常可以看到GPIO端口后边接很长一串,比如PA2/USART2_TX/ADC123_IN2/TIM5_CH3/TIM2_CH3
,意思就是PA2引脚除了可以作为简单的I/O输入输出电平,还可以有复用功能,可以复用为USART2_TX、ADC123_IN2……。
从原理图来看,比如PA2,可以作为USART2的发送端,也可以作为ADC123_IN2/TIM5_CH3/TIM2_CH3端来使用
因此,这就是
在stm32中外设太多了,因此如果这个外设默认使用的引脚被其它外设占用了,那就使用其它引脚,这就是
比如USART2,默认是使用PA2、PA3的,但如果这两个引脚被占用了(被其它设备使用了),就可以重映射到其它引脚,重映射到哪个引脚,这要查表(在《STM32F1xx中文参考手册》8.3中有),人家已经规定好重映射时可以使用哪个引脚,比如USART2的TX和RX端可以重映射到PD5、PD6
总结:复用和重映射是同一个概念,只是对于GPIO来说是复用,对于外设来说是重映射
另外,从外设的角度来看,某些外设的重映射分为三种
- 不使用重映射
- 使用部分重映射
- 使用完全重映射
也就是说,某些外设可以关联到三种不同的GPIO,具体看你想要用以上的哪一种重映射方案。以定时器3输出PWM信号为例,其不同通道映射到不同的GPIO引脚,如图:
假如想要使用通道2生成PWM信号,这时可以选择通过PA7/PB5/PC7进行输出,接下来如果想要通过PB5进行输出,就要对定时器3采用【部分重映射】方案,具体如何通过代码配置,看下面最后的一部分。
常用外设的重映射功能,点击查看
如何使用重映射
如上面所说,当某个外设的默认使用的GPIO被占用了,就可以重映射到其它GPIO,那么如何使用呢,继续以定时器3为例,主要分为以下几步:
-
查看手册,了解自己想要使用的外设都可以映射到哪些GPIO引脚,比如定时器3的CH2通道
-
开启GPIOx时钟,开启外设时钟,打开AFIO时钟,配置外设的重映射方案,配置GPIO的输出模式为
GPIO_Mode_AF_PP
【假如使用PB5(即部分重映射)进行输出】
1
2
3
4
5
6
7
8
9
10RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能定时器3时钟
RCC_APB1PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能AFIO时钟(好像有些情况可以不打开,本人不太清除,具体还得查手册,不过开了也没事)
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); // 对TIM3使用【部分重映射】
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);【假如使用PA7(即不使用重映射)进行输出】
1
2
3
4
5
6
7
8
9
10RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能定时器3时钟
// RCC_APB1PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 不使用重映射不需要开启
// GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); // 【不使用重映射】就不需要配置重映射方案
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出(注意,只要是外设的输出都要使用GPIO_Mode_AF_PP,即便没有使用重映射)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);【假如使用PC7(使用完全重映射)进行输出】
1
2
3
4
5
6
7
8
9
10RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 使能GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能定时器3时钟
RCC_APB1PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 开启AFIO时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); // 配置重映射方案
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
再举个例子,配置USART2的重映射
-
查阅手册,发现只有2种映射方案,默认(不重映射时)通过PA2发送,PA3接收,这里我们选择通过PD5发送,PD6接收
-
打开GPIO时钟,打开USART2外设时钟,打开AFIO时钟,配置外设的重映射方案,配置GPIO的输出模式为
GPIO_Mode_AF_PP
只需要打开AFIO时钟和相应外设(例如USART2)的重映射功能即可,如:
1 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // 使能GPIOD时钟 |