在写程序时遇到想要的端口功能,而这个引脚又被其它的功能占用了无法删除掉或直接使用,这种情况就很尴尬了,因为STM32同一个引脚是不能同时使用两个功能的。那么遇到这种情况就需要考虑该端口分时复用或者端口重映射功能了。
硬件平台使用的是STM32F103ZET6芯片。
打开对应芯片数据手册,找到 pin outs and pin descriptions 章节。
如下图所示:
往下拉就可以看到芯片的相关引脚定义了,如下图这个就是我使用的芯片引脚定义,用的是STM32F103ZET6的芯片。
再往下拉,就可以看到下面这个引脚定义及功能详细表了。
1.pins这栏是芯片型号,看对应芯片封装就可以,STM32F103ZET6芯片是LQFP144的,所以对应看该列即可。
2.pin name 顾名思义就是引脚的名字,可对应前面的引脚标号。
3.default 是芯片该引脚能支持的功能,复位后的引脚功能。
4.remap 是芯片端口重映射的功能,如果表格是空白的,则说明该引脚不支持重映射其它功能。
在正常一般情况下STM32F1默认串口1的发送和接收引脚是PA9和PA10的。如下图所示:
由于实验需要验证这个串口1的重映射功能是否可以正常使用,所以使用PB6和PB7两个引脚来重映射串口1功能。如下图所示:
由前面数据手册可知PB6和PB7这两个引脚可以用来实现串口1功能,所以程序只需要初始化该两个引脚即可,PA9和PA10就不需要再初始化了。
本实验使用的是标准库的例程,直接使用了正点原子的串口实验进行修改的。只需要使能对应的时钟和把串口引脚对应改下就可以了。
1,使能时钟。
2,初始化串口引脚。
如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOB, ENABLE); //使能USART1,GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能复用时钟
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE); //使能串口1重映射时钟
示例代码如下:
void uart_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOB, ENABLE); //使能USART1,GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
//USART1_TX GPIOB.6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PB.6
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.6
//USART1_RX GPIOB.7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//PB.7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.7
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
需要改的就这个串口初始化函数,其它的代码都不要修改了。
把开发板TTL电路的TX和RX分别接到PB7和PB6引脚上,或者之间用USB-TTL模块也可以。
打开串口调试助手,选择对应的波特率就可以看到收发的内容了,说明这样设置是正常的。
注意:实验要勾选发送新行才能正常发送内容。
要完成这个功能还是比较简单的,只要懂看明白这个表格就可以了。
同理,其它的外设功能也一样,比如定时器、ADC等等,都是按照这个方法原理来就可以了。