6回答

0收藏

STM32基于CubeMX的高速串口收发程序(中断模式)

其他 其他 3093 人阅读 | 6 人回复 | 2020-04-01

STM32基于STM32CubeMX的高速串口收发程序(中断模式)
看到大家经常写一些关于串口的问题,我也尝试开一个使用串口的工程。
简单的要求是,USART1和USART2之间互相转发。
发现使用CubeMX平台,建立测试工程没有难度,情况如下:
1. 配置管脚,使用BluePill最小板,PC13接有LED
MCU是STM32F103C8T6,这个不重要. 不要忘记配置SWD调试接口


2. 配置时钟,重点已经标出:


3. 配置中断选项,由于不使用DMA,可以不理DMA的选项:
(USART2也要同样配置)

(然后,生成工程代码)
4. 添加代码
4.1 在main的初始化部分,添加接收中断使能:
  • 1. __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //enable Rx INT
  • 2. __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE); //enable Rx INT

[color=rgb(51, 102, 153) !important]复制代码


4.2 打开stm32f1xx_it.c,在前面添加接收缓存结构体:
  • 1. /* USER CODE BEGIN 0 */
  • 2. #define UART_BUFFER_SIZE    64 //here must be 2^n
  • 3. struct bufer_st {
  • 4.   unsigned int in;                // Next In Index
  • 5.   unsigned int out;               // Next Out Index
  • 6.   char buffer [UART_BUFFER_SIZE]; // Buffer
  • 7. };
  • 8. static struct bufer_st uart1buffer = { 0, 0, };
  • 9. static struct bufer_st uart2buffer = { 0, 0, };
  • 10. /* USER CODE END 0 */

[color=rgb(51, 102, 153) !important]复制代码



4.3 在stm32f1xx_it.c的底下,修改USART1和USART2的中断服务程序如下:
  • 1. /**
  • 2. * @Brief This function handles USART1 global interrupt.
  • 3. */
  • 4. void USART1_IRQHandler(void)
  • 5. {
  • 6.   /* USER CODE BEGIN USART1_IRQn 0 */
  • 7.   struct bufer_st *p;
  • 8.   /* USER CODE END USART1_IRQn 0 */
  • 9.   HAL_UART_IRQHandler(&huart1);
  • 10.   /* USER CODE BEGIN USART1_IRQn 1 */
  • 11.   p = &uart1buffer; //use UART1 buffer
  • 12.
  • 13.   //raed UART1
  • 14.   IF (USART1->SR & UART_IT_RXNE) // read interrupt
  • 15.   {
  • 16.     USART1->SR &= ~UART_IT_RXNE; // clear interrupt
  • 17.
  • 18.     if (((p->in - p->out) & ~(UART_BUFFER_SIZE-1)) == 0) {
  • 19.       p->buffer[p->in & (UART_BUFFER_SIZE-1)] = (USART1->DR & 0xFF); //read DATA
  • 20.       p->in++;
  • 21.     }
  • 22.   }
  • 23.   //send to UART2
  • 24.   if (p->in != p->out)
  • 25.   {
  • 26.     USART2->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out
  • 27.     p->out++;
  • 28.   }
  • 29.   /* USER CODE END USART1_IRQn 1 */
  • 30. }
  • 31.
  • 32. /**
  • 33. * @brief This function handles USART2 global interrupt.
  • 34. */
  • 35. void USART2_IRQHandler(void)
  • 36. {
  • 37.   /* USER CODE BEGIN USART2_IRQn 0 */
  • 38.   struct bufer_st *p;
  • 39.   /* USER CODE END USART2_IRQn 0 */
  • 40.   HAL_UART_IRQHandler(&huart2);
  • 41.   /* USER CODE BEGIN USART2_IRQn 1 */
  • 42.   p = &uart2buffer; //use UART2 buffer
  • 43.
  • 44.   //raed UART2
  • 45.   if (USART2->SR & UART_IT_RXNE) // read interrupt
  • 46.   {
  • 47.     USART2->SR &= ~UART_IT_RXNE; // clear interrupt
  • 48.
  • 49.     if (((p->in - p->out) & ~(UART_BUFFER_SIZE-1)) == 0)
  • 50.     {
  • 51.       p->buffer[p->in & (UART_BUFFER_SIZE-1)] = (USART2->DR & 0xFF); //read DATA
  • 52.       p->in++;
  • 53.     }
  • 54.   }
  • 55.   //send to UART1
  • 56.   if (p->in != p->out)
  • 57.   {
  • 58.     USART1->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out
  • 59.     p->out++;
  • 60.   }
  • 61.   /* USER CODE END USART2_IRQn 1 */
  • 62. }


[color=rgb(51, 102, 153) !important]复制代码


(看得出,中断里面是收到一个字符发送一个字符。 发送是直接发送,不处理发送中断。)
大功告成了!! 编译后烧录。
测试条件,使用两个UART转USB板子(FTDI)和sscom5上位机程序(开两个),发送区都摆放700多个字符,以10ms的间隔连续发送。
测试结果,速度115200bps和1Mbps,双向同时收发100万字符无差错。 2Mbps,单方向100万字符无差错。
(高速测试时,需要修改main.c里面的串口速度BaudRate配置。 我没有测试“自动波特率”的模式是否正常。)
完整代码请见附件。


游客,如果您要查看本帖隐藏内容请回复






分享到:
回复

使用道具 举报

回答|共 6 个

倒序浏览

板凳

人事已尽

发表于 2021-11-9 13:23:42 | 只看该作者

老哥 附件在哪里啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条