你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
radio2radio 发布时间:2018-7-14 21:15
本帖最后由 radio2radio 于 2018-7-14 23:51 编辑

看到大家经常写一些关于串口的问题,我也尝试开一个使用串口的工程。
简单的要求是,USART1和USART2之间互相转发
发现使用CubeMX平台,建立测试工程没有难度,情况如下:

1. 配置管脚,使用BluePill最小板,PC13接有LED:
MCU是STM32F103C8T6,这个不重要. 不要忘记配置SWD调试接口。
0.JPG

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

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

(然后,生成工程代码)

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
复制代码


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 */
复制代码



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.     if (((p->in - p->out) & ~(UART_BUFFER_SIZE-1)) == 0) {
  18.       p->buffer[p->in & (UART_BUFFER_SIZE-1)] = (USART1->DR & 0xFF); //read DATA
  19.       p->in++;
  20.     }
  21.   }
  22.   //send to UART2
  23.   if (p->in != p->out)
  24.   {
  25.     USART2->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out
  26.     p->out++;
  27.   }
  28.   /* USER CODE END USART1_IRQn 1 */
  29. }

  30. /**
  31. * @brief This function handles USART2 global interrupt.
  32. */
  33. void USART2_IRQHandler(void)
  34. {
  35.   /* USER CODE BEGIN USART2_IRQn 0 */
  36.   struct bufer_st *p;
  37.   /* USER CODE END USART2_IRQn 0 */
  38.   HAL_UART_IRQHandler(&huart2);
  39.   /* USER CODE BEGIN USART2_IRQn 1 */
  40.   p = &uart2buffer; //use UART2 buffer
  41.   
  42.   //raed UART2
  43.   if (USART2->SR & UART_IT_RXNE) // read interrupt
  44.   {                  
  45.     USART2->SR &= ~UART_IT_RXNE; // clear interrupt

  46.     if (((p->in - p->out) & ~(UART_BUFFER_SIZE-1)) == 0)
  47.     {
  48.       p->buffer[p->in & (UART_BUFFER_SIZE-1)] = (USART2->DR & 0xFF); //read DATA
  49.       p->in++;
  50.     }
  51.   }
  52.   //send to UART1
  53.   if (p->in != p->out)
  54.   {
  55.     USART1->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out
  56.     p->out++;
  57.   }
  58.   /* USER CODE END USART2_IRQn 1 */
  59. }
复制代码

(看得出,中断里面是收到一个字符发送一个字符。 发送是直接发送,不处理发送中断。)

大功告成了!! 编译后烧录。

测试条件,使用两个UART转USB板子(FTDI)和sscom5上位机程序(开两个),发送区都摆放700多个字符,以10ms的间隔连续发送。
测试结果,速度115200bps和1Mbps,双向同时收发100万字符无差错2Mbps,单方向100万字符无差错。
(高速测试时,需要修改main.c里面的串口速度BaudRate配置。 我没有测试“自动波特率”的模式是否正常。)

最后,完整的工程见附件。

STM32F103-USART-CUBE.rar

下载

599.08 KB, 下载次数: 425

评分

参与人数 1 ST金币 +12 收起 理由
g921002 + 12 很给力!

查看全部评分

收藏 8 评论21 发布时间:2018-7-14 21:15

举报

21个回答
zero99 回答时间:2018-7-16 17:11:27
学习了
玉宇swh 回答时间:2018-7-21 21:45:32
谢谢分享!
annqian 回答时间:2018-7-30 17:00:14
不错
yesterdat 回答时间:2018-8-3 07:39:01
本帖最后由 yesterdat 于 2018-8-3 08:35 编辑

谢谢楼主,解决了我的HAL库不能单字节中断收发的问题!
  • void USART1_IRQHandler(void)
  • {
  •   /* USER CODE BEGIN USART1_IRQn 0 */
  •   struct bufer_st *p;
  •   /* USER CODE END USART1_IRQn 0 */
  •   HAL_UART_IRQHandler(&huart1);
  •   /* USER CODE BEGIN USART1_IRQn 1 */
  •   p = &uart1buffer; //use UART1 buffer
  •   //raed UART1
  •   if (USART1->SR & UART_IT_RXNE) // read interrupt
  •   {
  •     USART1->SR &= ~UART_IT_RXNE; // clear interrupt
  •     if (((p->in - p->out) & ~(UART_BUFFER_SIZE-1)) == 0) {
  •       p->buffer[p->in & (UART_BUFFER_SIZE-1)] = (USART1->DR & 0xFF); //read DATA
  •       p->in++;
  •     }
  •   }
  •   //send to UART2
  •   if (p->in != p->out)
  •   {
  •     USART2->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out,此处我将USART2修改成USART1,就能实现每个字节接收中断收发
  •     p->out++;
  •   }
  •   /* USER CODE END USART1_IRQn 1 */
  • }



stm1024 回答时间:2018-8-3 08:53:34
看标题以为采用DMA
wwwheihei 回答时间:2018-8-13 17:22:46
USART2->DR = (p->buffer[p->out & (UART_BUFFER_SIZE-1)] & 0xFF); //send out,此处我将USART2修改成USART1,就能实现每个字节接收中断收发

当你把数据送到dr寄存器后,你没判断发送完成寄存器啊?会不会覆盖数据呢?
radio2radio 回答时间:2018-8-13 19:42:28
wwwheihei 发表于 2018-8-13 17:22
USART2->DR = (p->buffer & 0xFF); //send out,此处我将USART2修改成USART1,就能实现每个字节接收中断收 ...

不会,因为收到1个字节之后发送一个字节,写入DR是瞬间完成,收发速度相同,不会有重叠的。
wwwheihei 回答时间:2018-8-14 08:30:08
radio2radio 发表于 2018-8-13 19:42
不会,因为收到1个字节之后发送一个字节,写入DR是瞬间完成,收发速度相同,不会有重叠的。
...

1.那你搞的那个数组有啥用啊,看似环形数组,那还不如直接收到一个数据然后直接给dr寄存器,
2.写入dr寄存器很快,但是发送完成又是另外一会事情
radio2radio 回答时间:2018-8-14 10:23:17
wwwheihei 发表于 2018-8-14 08:30
1.那你搞的那个数组有啥用啊,看似环形数组,那还不如直接收到一个数据然后直接给dr寄存器,
2.写入dr寄存 ...

1. 同意您的说法,数组并不重要。反正是收到一个字节发送一个字节。
2. 串口的速度,相对于MCU的运行速度是慢太多,由于收发的速度相同,近似于“同步状态”,接收和发送是受硬件控制同时进行的,收到一个字节,触发中断进行处理,处理中断这个时候,上一个字节刚好发送完成。所以不会重叠的。

123下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版