抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

复用与重映射

在芯片原理图上经常可以看到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端来使用

image-20211003204319883

因此,这就是复用,即某个GPIO可以被多个设备使用,但同时只能被一个设备使用,因此如果这个GPIO被某个设备占用了怎么办,莫慌,一个外设除了可以默认使用这个GPIO外,还可以使用其它GPIO,这就是接下来要讲的重映射

在stm32中外设太多了,因此如果这个外设默认使用的引脚被其它外设占用了,那就使用其它引脚,这就是重映射

比如USART2,默认是使用PA2、PA3的,但如果这两个引脚被占用了(被其它设备使用了),就可以重映射到其它引脚,重映射到哪个引脚,这要查表(在《STM32F1xx中文参考手册》8.3中有),人家已经规定好重映射时可以使用哪个引脚,比如USART2的TX和RX端可以重映射到PD5、PD6

image-20211003211345300

总结:复用和重映射是同一个概念,只是对于GPIO来说是复用,对于外设来说是重映射

另外,从外设的角度来看,某些外设的重映射分为三种

  1. 不使用重映射
  2. 使用部分重映射
  3. 使用完全重映射

也就是说,某些外设可以关联到三种不同的GPIO,具体看你想要用以上的哪一种重映射方案。以定时器3输出PWM信号为例,其不同通道映射到不同的GPIO引脚,如图:

image-20240331220705297

假如想要使用通道2生成PWM信号,这时可以选择通过PA7/PB5/PC7进行输出,接下来如果想要通过PB5进行输出,就要对定时器3采用【部分重映射】方案,具体如何通过代码配置,看下面最后的一部分。

常用外设的重映射功能,点击查看

image-20211003210301621

image-20211003210900054

image-20211003210919142

image-20211003210948796

image-20211003211005598

image-20211003211053335

image-20211003211114080

image-20211003211134467

如何使用重映射

如上面所说,当某个外设的默认使用的GPIO被占用了,就可以重映射到其它GPIO,那么如何使用呢,继续以定时器3为例,主要分为以下几步:

  1. 查看手册,了解自己想要使用的外设都可以映射到哪些GPIO引脚,比如定时器3的CH2通道

    image-20240331220705297

  2. 开启GPIOx时钟,开启外设时钟,打开AFIO时钟,配置外设的重映射方案,配置GPIO的输出模式为 GPIO_Mode_AF_PP

    【假如使用PB5(即部分重映射)进行输出】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    RCC_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
    10
    RCC_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
    10
    RCC_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的重映射

  1. 查阅手册,发现只有2种映射方案,默认(不重映射时)通过PA2发送,PA3接收,这里我们选择通过PD5发送,PD6接收

    image-20240331223658637

  2. 打开GPIO时钟,打开USART2外设时钟,打开AFIO时钟,配置外设的重映射方案,配置GPIO的输出模式为 GPIO_Mode_AF_PP

只需要打开AFIO时钟和相应外设(例如USART2)的重映射功能即可,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);  // 使能GPIOD时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能 AFIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART2时钟
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); // 开启重映射(不重映射也不需要这行代码),由于只有2种重映射方案,因此名称中不含Partial或Full

// 配置PD5
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(GPIOD, &GPIO_InitStructure);

//配置PD6,只需要改引脚,其它不变
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStructure);

禁用重映射功能

有些引脚在系统复位后就被某些外设专用,即默认只能被这些设备使用,但有时不想用这些设备,于是可以禁用这些设备的重映射功能,释放相关的GPIO,这时这些GPIO就变成普通IO了

比如禁用JTAG-DP调试接口:

1
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); 

评论