硬件资源
-
STM32F103C8T6 开发板
-
DAP-Link
最近的一个项目要用到 USART1,但其默认端口 PA9 和 PA10 拿去驱动电机了,所以得用 PB7 和 PB6 作为串口的端口。
原先用于串口通信的代码(修改自正点原子)在使用 PA9/10 时可以正常工作,但当我将端口改为 PB6/7 时就无法正常工作了,查了一下,发现是没有添加串口重映射的一行代码,但是添加之后还是无法工作。于是我用 STM32CubeMX 生成了一个串口重映射的新工程,经过对比,发现缺失的是以下两行代码:
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_USART1_ENABLE();
将之前的代码和新工程的代码整合一下之后,完整代码如下,亲测可用:
graph TD
A[HAL_Init]-->B[HAL_MspInit 使能端口复用时钟]
B-->C[Uart1_Init 使能端口时钟 配置串口1]
C-->D[HAL_UART_MspInit 使能串口时钟 初始化端口 配置串口重映射 初始化串口中断]
bsp_usart.h
#ifndef __BSP_USART_H
#define __BSP_USART_H
#include "stm32f1xx.h"
#include <stdio.h>
//串口波特率
#define USART_BAUDRATE 115200
//引脚定义
/*******************************************************/
#define USARTx USART1
#define USART_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE();
#define USART_CLK_DISABLE() __HAL_RCC_USART1_CLK_DISABLE();
#define USART_RX_GPIO_PORT GPIOB
#define USART_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USART_RX_PIN GPIO_PIN_7
#define USART_TX_GPIO_PORT GPIOB
#define USART_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USART_TX_PIN GPIO_PIN_6
#define USART_REMAP_ENABLE() __HAL_AFIO_REMAP_USART1_ENABLE()
#define USART_IRQHandler USART1_IRQHandler
#define USART_IRQ USART1_IRQn
/************************************************************/
//初始化串口,在主函数中调用
void Uart1_Init(void);
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
extern UART_HandleTypeDef huart1;
#endif
bsp_usart.c
#include "./usart/bsp_usart.h"
UART_HandleTypeDef huart1;
void Uart1_Init(void){
USART_TX_GPIO_CLK_ENABLE();
USART_RX_GPIO_CLK_ENABLE();
huart1.Instance = USARTx;
huart1.Init.BaudRate = USART_BAUDRATE;//波特率:115200
huart1.Init.WordLength = UART_WORDLENGTH_8B;//数据位长度:8
huart1.Init.StopBits = UART_STOPBITS_1;//停止位长度:1
huart1.Init.Parity = UART_PARITY_NONE;//校验位:无
huart1.Init.Mode = UART_MODE_TX_RX;//通信模式:收发
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;//硬件流量控制:关闭
huart1.Init.OverSampling = UART_OVERSAMPLING_16;//过采样模式
HAL_UART_Init(&huart1);
}
//被 HAL_UART_Init 调用
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance == USARTx)
{
USART_CLK_ENABLE();
USART_TX_GPIO_CLK_ENABLE();
USART_RX_GPIO_CLK_ENABLE();
/**
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = USART_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(USART_TX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USART_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USART_RX_GPIO_PORT, &GPIO_InitStruct);
USART_REMAP_ENABLE();
/* 初始化串口中断 */
HAL_NVIC_SetPriority(USART_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(USART_IRQ);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance == USARTx)
{
USART_CLK_DISABLE() ;
/**
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(USART_RX_GPIO_PORT, USART_RX_PIN | USART_TX_PIN);
HAL_NVIC_DisableIRQ(USART_IRQ);
}
}
//重定向c库函数printf到串口USART1,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
//重定向c库函数scanf到串口USART1,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
int ch;
HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
stm32f1xx_hal_msp.c
#include "main.h"
//被 HAL_Init 调用
void HAL_MspInit(void)
{
__HAL_RCC_AFIO_CLK_ENABLE();//开启端口复用时钟
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_AFIO_REMAP_SWJ_NOJTAG();//SWD调试重映射
}
stm32f1xx_it.c
//串口中断服务函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}