stm32 使用多串口通信调试总结
2023-09-11 14:17:10 时间
前记:
stm32使用多个串口通信,这个项目遇到了不少问题,值得反思和深入总结一下。
提纲:
这次的问题,主要有几个部分组成:
A 多串口的DMA配置,这个需要注意,尽量不要使用同一个DMA通道,这个高速的接收数据的时候会出问题。
B 串口的tx和rx配置一定要检查好,不要被复用了。这个是经常遇到的坑。
C 串口的接收完成中断里面尽量少做事情。
源码解析:
这里面注意几个细节:
一个是串口中断的设置,如源码所示:
/** * @brief This function handles DMA1 channel6 global interrupt. */ void DMA1_Channel6_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ /* USER CODE END DMA1_Channel6_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart2_rx); /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ /* USER CODE END DMA1_Channel6_IRQn 1 */ } /** * @brief This function handles DMA1 channel6 global interrupt. */ void DMA1_Channel3_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ /* USER CODE END DMA1_Channel6_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart3_rx); /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ /* USER CODE END DMA1_Channel6_IRQn 1 */ }
另外一个是串口的配置,如下所示:
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2; PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 DMA Init */ /* USART2_RX Init */ hdma_usart2_rx.Instance = DMA1_Channel6; hdma_usart2_rx.Init.Request = DMA_REQUEST_2; hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart2_rx.Init.Mode = DMA_NORMAL; hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 8, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); /* USER CODE BEGIN USART2_MspInit 1 */ __HAL_UART_CLEAR_IDLEFLAG(&huart2); HAL_UART_Receive_DMA(&huart2, SENSOR_RX_BUFF, GPS_RX_BUFF_SIZE); __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); /* USER CODE END USART2_MspInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3; PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } /* USART2 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART2 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART2 DMA Init */ /* USART2_RX Init */ hdma_usart3_rx.Instance = DMA1_Channel3; hdma_usart3_rx.Init.Request = DMA_REQUEST_2; hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart3_rx.Init.Mode = DMA_NORMAL; hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart3_rx); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 8, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); // /* USER CODE BEGIN USART2_MspInit 1 */ __HAL_UART_CLEAR_IDLEFLAG(&huart3); HAL_UART_Receive_DMA(&huart3, GPS_RX_BUFF, GPS_RX_BUFF_SIZE); __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE); /* USER CODE END USART2_MspInit 1 */ } else if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /** Initializes the peripherals clock */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // /* USART2 DMA Init */ // /* USART2_RX Init */ // hdma_usart1_rx.Instance = DMA1_Channel6; // hdma_usart1_rx.Init.Request = DMA_REQUEST_2; // hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; // hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; // hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; // hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; // hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; // hdma_usart1_rx.Init.Mode = DMA_NORMAL; // hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; // if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) // { // Error_Handler(); // } // __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 8, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } }
总结:
这个是三个串口正常工作的版本,有一个串口不需要接受数据,就把接收毙掉了。目前三个串口有好的同时工作。
相关文章
- Windbg调试Unity3d 卡死 无响应等问题测试
- 基于.Net C# 通信开发-网络调试助手
- modbus-poll和modbus-slave工具的学习使用——modbus协议功能码3的解析(及欧姆龙温控器调试笔记)
- Python爬虫技术--基础篇--错误,调试和测试(中)
- 如何远程调试运行在嵌入式设备上的用户空间程序?
- Nginx日志配置及配置调试
- 《Effective Debugging:软件和系统调试的66个有效方法》——第1章 宏观策略 第1条:通过事务追踪系统处理所有的问题
- Qt编写气体安全管理系统27-设备调试
- Xcode8的调试技能Memory Graph 实战解决闭包引用循环问题
- 浏览器调试之重新发送请求
- android11开启无线调试
- 【AGC】在云调试删除应用无法再安装问题
- Linux下图形界面调试工具kdbg安装及測试
- 关于Unity中调试C#的方法
- JDY-19蓝牙模块介绍及主、从机调试演示
- 软件调试实战入门(2)
- webpack中编写自定义loader和plugin,及如何调试(debug)webpack,vuecli等脚手架
- VSCode 快速创建H5并调试