.UART_HardwareFlowControl = UART_HWCONTROL_NONE, //无硬件数据流控制
.UART_Mode = UART_MODE_TX_RX, //收发模式
.UART_Parity = UART_PARITY_NONE, //无校验位
.UART_StopBits = UART_STOPBITS_1, //一停止位
.UART_WordLength = UART_WORDLENGTH_8B, //数据位为8位
.UART_BaudRate = bound //波特率
};
if(HAL_UART_Init(&UART2_Handler) != HAL_OK){
error_handler(); //初始化失败,死循环
}
//使能 UART 接收 DMA 方式
__HAL_RCC_DMA1_CLK_ENABLE(); //使能 DMA1 时钟
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 3, 3); //DMA 通道6中断通道设置
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); //DMA 通道6中断使能
UART2RxDMA_Handler.Instance = DMA1_Channel6; //DMA通道选择
UART2RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
UART2RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE; //外设不增量
UART2RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE; //内存增量
UART2RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8位
UART2RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //内存数据宽度为8位
UART2RxDMA_Handler.Init.Mode = DMA_NORMAL; //普通模式
UART2RxDMA_Handler.Init.Priority = DMA_PRIORITY_LOW; //优先级为低
HAL_DMA_Init(&UART2RxDMA_Handler); //初始化 DMA 外设
__HAL_LINKDMA(&UART2_Handler,hdmarx,UART2RxDMA_Handler); //连接 UART2 的 DMA
HAL_UART_Receive_DMA(&UART2_Handler,g_uart2_buff,LEN_UART2_RECV_BUFF); //启动 DMA 传输
}
这里需要注意的是,如果使用 DMA 收发,需要在 stm32f1xx_it.c 中添加 DMA 传输完成中断的处理函数 DMA1_Channel6_IRQHandler()。
初始写法是没有优先级等级的,可以无脑设置成最高的,但之后代码升级优化就会出现问题。这里直接复制下在 H7 和 F4 上正常的写法:
#define DMA_UART_RX_STREAM DMA2_Stream2
#define DMA_UART_RX_CHANNEL DMA_CHANNEL_4
#define DMA_UART_RX_IRQn DMA2_Stream2_IRQn
#define DMA_UART_RX_IRQ_HANDLER DMA2_Stream2_IRQHandler
#define DMA_UART_TX_STREAM DMA2_Stream7
#define DMA_UART_TX_CHANNEL DMA_CHANNEL_4
#define DMA_UART_TX_IRQn DMA2_Stream7_IRQn
#define DMA_UART_TX_IRQ_HANDLER DMA2_Stream7_IRQHandler
DMA_HandleTypeDef hdma_uart_rx;
DMA_HandleTypeDef hdma_uart_tx;
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA_UART_RX_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA_UART_RX_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA_UART_TX_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA_UART_TX_IRQn);
}
void MX_USART2_UART_Init(uint32_t baud_rate)
{
/* USART2 parameter configuration */
huart2.Instance = USART2;
huart2.Init.BaudRate = baud_rate;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* Configure DMA channels */
hdma_uart_rx.Instance = DMA_UART_RX_STREAM;
hdma_uart_rx.Init.Channel = DMA_UART_RX_CHANNEL;
hdma_uart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart_rx.Init.Mode = DMA_CIRCULAR;
hdma_uart_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_uart_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart2, hdmarx, hdma_uart_rx);
hdma_uart_tx.Instance = DMA_UART_TX_STREAM;
hdma_uart_tx.Init.Channel = DMA_UART_TX_CHANNEL;
hdma_uart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_uart_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart_tx.Init.Mode = DMA_NORMAL;
hdma_uart_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_uart_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart2, hdmatx, hdma_uart_tx);
}
以上就是 stm32f103ze nano3.1.5 版本串口 DMA 接收配置的详细配置方法和解决报错问题的相关材料。如果在移植的过程中仍有疑问或其他问题,可以参考以上内容进行解决。
.UART_HardwareFlowControl = UART_HWCONTROL_NONE, //无硬件数据流控制
.UART_Mode = UART_MODE_TX_RX, //收发模式
.UART_Parity = UART_PARITY_NONE, //无校验位
.UART_StopBits = UART_STOPBITS_1, //一停止位
.UART_WordLength = UART_WORDLENGTH_8B, //数据位为8位
.UART_BaudRate = bound //波特率
};
if(HAL_UART_Init(&UART2_Handler) != HAL_OK){
error_handler(); //初始化失败,死循环
}
//使能 UART 接收 DMA 方式
__HAL_RCC_DMA1_CLK_ENABLE(); //使能 DMA1 时钟
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 3, 3); //DMA 通道6中断通道设置
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); //DMA 通道6中断使能
UART2RxDMA_Handler.Instance = DMA1_Channel6; //DMA通道选择
UART2RxDMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
UART2RxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE; //外设不增量
UART2RxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE; //内存增量
UART2RxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8位
UART2RxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //内存数据宽度为8位
UART2RxDMA_Handler.Init.Mode = DMA_NORMAL; //普通模式
UART2RxDMA_Handler.Init.Priority = DMA_PRIORITY_LOW; //优先级为低
HAL_DMA_Init(&UART2RxDMA_Handler); //初始化 DMA 外设
__HAL_LINKDMA(&UART2_Handler,hdmarx,UART2RxDMA_Handler); //连接 UART2 的 DMA
HAL_UART_Receive_DMA(&UART2_Handler,g_uart2_buff,LEN_UART2_RECV_BUFF); //启动 DMA 传输
}
这里需要注意的是,如果使用 DMA 收发,需要在 stm32f1xx_it.c 中添加 DMA 传输完成中断的处理函数 DMA1_Channel6_IRQHandler()。
初始写法是没有优先级等级的,可以无脑设置成最高的,但之后代码升级优化就会出现问题。这里直接复制下在 H7 和 F4 上正常的写法:
#define DMA_UART_RX_STREAM DMA2_Stream2
#define DMA_UART_RX_CHANNEL DMA_CHANNEL_4
#define DMA_UART_RX_IRQn DMA2_Stream2_IRQn
#define DMA_UART_RX_IRQ_HANDLER DMA2_Stream2_IRQHandler
#define DMA_UART_TX_STREAM DMA2_Stream7
#define DMA_UART_TX_CHANNEL DMA_CHANNEL_4
#define DMA_UART_TX_IRQn DMA2_Stream7_IRQn
#define DMA_UART_TX_IRQ_HANDLER DMA2_Stream7_IRQHandler
DMA_HandleTypeDef hdma_uart_rx;
DMA_HandleTypeDef hdma_uart_tx;
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA_UART_RX_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA_UART_RX_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA_UART_TX_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA_UART_TX_IRQn);
}
void MX_USART2_UART_Init(uint32_t baud_rate)
{
/* USART2 parameter configuration */
huart2.Instance = USART2;
huart2.Init.BaudRate = baud_rate;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* Configure DMA channels */
hdma_uart_rx.Instance = DMA_UART_RX_STREAM;
hdma_uart_rx.Init.Channel = DMA_UART_RX_CHANNEL;
hdma_uart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart_rx.Init.Mode = DMA_CIRCULAR;
hdma_uart_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_uart_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart2, hdmarx, hdma_uart_rx);
hdma_uart_tx.Instance = DMA_UART_TX_STREAM;
hdma_uart_tx.Init.Channel = DMA_UART_TX_CHANNEL;
hdma_uart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_uart_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart_tx.Init.Mode = DMA_NORMAL;
hdma_uart_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_uart_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&huart2, hdmatx, hdma_uart_tx);
}
以上就是 stm32f103ze nano3.1.5 版本串口 DMA 接收配置的详细配置方法和解决报错问题的相关材料。如果在移植的过程中仍有疑问或其他问题,可以参考以上内容进行解决。
举报