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

【经验分享】UART IDLE 中断使用-接收不定长串口数据

[复制链接]
STMCU小助手 发布时间:2022-2-15 22:07
前言
在串口通信应用中,我们常使用接受和发送中断,相信大家都不陌生。这里有个非常有用的中断可能被大家所忽略,即总线IDLE 中断。当一帧数据传输结束之后,总线会维持高电平状态,此时,就可以触发 MCU 的 IDLE 中断。在本文中,将介绍使用该中断来进行不定长串口数据接收的办法。通过该中断,可以省却很多用于检测数据传输是否完成的判断动作。
实验环境
   STM32F411RE-NUCLEO
   STM32CubeMX

总线状态分析
下图是发送 0xAA 0x55 的所抓取到的波形。从图中我们可以看到在发送该帧之前和之后,数据线处于 IDLE 的状态。在该帧中,字节与字节之间,没有 IDLE 状态出现,即不会出现 IDLE 误触发的情况。

G_YB)_J~CWYDHOKQS]P0.png

不定长数据接收
本次制作的工程是基于 HAL 库。在原生的 HAL 库中,并没有集成 IDLE 中断的处理。所以,在本文我们介绍的方法中,需要修改一些库文件来实现。

使用 STM32CubeMX 生成实验工程
工程的配置如下图:
1. 系统始终配置为 100MHz
2. 配置 USART2 为 Asynchrones,管脚配置为 PA2,PA3。
3. USART2 参数:9600Bits/s, 8bits, None,1Stop

{NA4%H92Q97)J{D5LUGEWAE.png

为了方便打印接收到的相关信息,需要对生成的工程做如下修改来映射 print 函数。
main.c-声明
  1. #ifdef __GNUC__
  2. /* With GCC, small printf (option LD Linker->Libraries->Small printf
  3. set to 'Yes') calls __io_putchar() */
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  5. #else
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  7. #endif /* __GNUC__ */
复制代码


main.c-Code
  1. /**

  2. * @brief Retargets the C library printf function to the USART.
  3. * @param None
  4. * @retval None
  5.   */
  6.   PUTCHAR_PROTOTYPE
  7.   {
  8.   /* Place your implementation of fputc here */
  9.   /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  10.   HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
  11.   return ch;
  12.   }
复制代码

  修改工程代码
  增加接收 Buffer

  main.c
  1.   //Modification 0
  2.   //Store the revceived bytes number
  3.   uint32_t Rev_Size = 0;
  4.   //Receive buffer
  5.   uint8_t UART_RX_Buf[15];
复制代码

  stm32f4xx_hal_uart.c
  1.   //Modification 0
  2.   extern uint32_t Rev_Size;
复制代码

  在接收函数中使能 IDLE 中断
stm32f4xx_hal_uart.c -> HAL_UART_IRQHandler ()函数
  1. //Modification 2
  2. if(((isrflags & USART_SR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
  3. {
  4. //Record the received bytes number
  5. Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->NDTR;
  6. //clear the IDLE flag
  7. __HAL_UART_CLEAR_IDLEFLAG(huart);
  8. //Abord the received process
  9. HAL_UART_AbortReceive_IT(huart);
  10. return;
  11. }
复制代码


接收完成处理(IDLE 产生,一帧数据传输完成)
stm32f4xx_hal_uart.c -> HAL_UART_AbortReceive_IT ()函数
  1. <div>//Modification 3</div><div>CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));</div><div>// CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));</div>
复制代码


main.c
  1. <div><div>//Modification 4</div><div>void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)</div><div>{</div><div> //Print received Bytes</div><div>printf("\n\r[IDLE]Received %d Bytes:",Rev_Size);</div></div><div><div>for(uint16_t i = 0; i < Rev_Size; i++)</div><div>{</div><div>printf(" 0x%02X", UART_RX_Buf[i]);</div><div>}</div><div>//Re-start receiving</div><div>HAL_UART_Receive_DMA(&huart2, UART_RX_Buf, 15);</div><div> /* NOTE : This function should not be modified, when the callback is needed,</div><div> the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file.</div><div> */</div><div>}</div></div>
复制代码



使能接收
main.c
  1. <div>//Modification 5. ‘15’ is the total number to be received. Make sure it can cover the</div><div>longest frame.</div><div> HAL_UART_Receive_DMA(&huart2, UART_RX_Buf, 15);</div>
复制代码


实验结果
使用串口调试串口,通过 STLINK 的虚拟串口发送数据,MCU 会返回接收多少个字节的数据,并将接收到的数据打印出来。
下图是发送 0xAA 0x55 的实验结果。


24I%WL`B_XX29`0L0N}JQ]E.png

小结
IDLE 作为指示总线空闲状态的中断,合理的使用能够很大程度的节省代码程序设计工作量。这里只是做个简单示范,抛砖引
玉,实际应用中希望大家可以灵活使用满足所需。



收藏 1 评论0 发布时间:2022-2-15 22:07

举报

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