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

【经验分享】stm32CubeMX+STM32F7串口空闲中断+发送DMA

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:07
1.配置系统下载程序方式

20200901143057124.png


2.RCC外部晶振

20200901143329762.png


3.串口声明

2020090114343042.png


2020090114350548.png


20200901143544740.png


4.系统时钟

20200901143654748.png


5.生成文件根据自己需求配置

20200901143817649.png


我这设置了所有库,可以选第二个仅需求的

20200901143845598.png


还加了其他功能,这里可不参考,DMA要放在串口前

20200901144049245.png


6.生成后修改

6.1 usart.h

  1. /* USER CODE BEGIN Includes */
  2. #include "stdio.h"
  3. #include "string.h"
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN Private defines */

  2. #define USART1_DMA_REC_SIE 256
  3. #define USART1_REC_SIE 512
  4. #define USART_DMA_SENDING 1//DMA发送
  5. #define USART_DMA_SENDOVER 0//DMA发送结束
  6. typedef struct
  7. {
  8.         uint8_t UsartRecFlag:1;//接收标志
  9.         uint8_t dmaSend_flag;//发送标志
  10.         uint16_t UsartDMAReclen;//DMA接收长度
  11.         uint16_t UsartReclen;//串口数据缓存长度
  12.         uint8_t Usart1DMARecBuffer[USART1_DMA_REC_SIE];//DMAbuffer缓存数据
  13.         uint8_t Usart1RecBuffer [USART1_REC_SIE] ;//串口1缓存数据
  14. }teUsart1type;

  15. extern teUsart1type Usart1type;//定义数据

  16. void UsartReceive_IDLE(UART_HandleTypeDef *huart);
  17. void Usart1SendData_DMA1(uint8_t *pdata, uint16_t Length);
  18. void Analysis_Serial_Data(void);
  19. void EnableUsart_IT(void);

  20. /* USER CODE END Private defines */
复制代码

6.2 usart.c,接收为双缓存方式,一般DMA接收放在,DMArec里,若不及时处理,下次接收会丢失,放入usartrec里,可避免,实现处理多少拿多少,dma接收的数据根据处理情况放入相应位置。

  1. teUsart1type Usart1type;
  2. /*****************************************************************************
  3. * 函 数 名  : EnableUsart_IT
  4. * 负 责 人  : by
  5. * 创建日期  : 2020年8月26日
  6. * 函数功能  : 串口2初始化函数,空闲与DMA中断
  7. * 输入参数  : 无
  8. * 输出参数  : 无
  9. * 返 回 值  :
  10. * 调用关系  :
  11. * 其    它  :   
  12. *****************************************************************************/
  13. void EnableUsart_IT(void)
  14. {   
  15.     __HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); // 开启串口2 空闲接收中断
  16.                 HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//DMA中断
  17. }
  18. /*****************************************************************************
  19. * 函 数 名  : Usart1SendData_DMA
  20. * 负 责 人  : by
  21. * 创建日期  : 2020年8月26日
  22. * 函数功能  : 串口2DMA发送函数
  23. * 输入参数  : 无
  24. * 输出参数  : 无
  25. * 返 回 值  :
  26. * 调用关系  :
  27. * 其    它  :   
  28. *****************************************************************************/
  29. void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  

  30. {  
  31.         //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
  32.         Usart1type.dmaSend_flag = USART_DMA_SENDING;  
  33.         HAL_UART_Transmit_DMA(&huart2, pdata, Length);  
  34. }  
  35. /*****************************************************************************
  36. * 函 数 名  : HAL_UART_TxCpltCallback
  37. * 负 责 人  : by
  38. * 创建日期  : 2020年8月26日
  39. * 函数功能  : 串口2DMA发送回调函数
  40. * 输入参数  : 无
  41. * 输出参数  : 无
  42. * 返 回 值  :
  43. * 调用关系  :
  44. * 其    它  :   
  45. *****************************************************************************/
  46. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  
  47. {  
  48.     __HAL_DMA_DISABLE(huart->hdmatx);
  49.     if(huart->Instance == huart2.Instance)        
  50.     Usart1type.dmaSend_flag = USART_DMA_SENDOVER;  
  51. }  
  52. /*****************************************************************************
  53. * 函 数 名  : UsartReceive_IDLE
  54. * 负 责 人  : by
  55. * 创建日期  : 2020年8月27日
  56. * 函数功能  : 串口接受空闲中断处理函数
  57. * 输入参数  : UART_HandleTypeDef *huart  串口句柄
  58. * 输出参数  : 无
  59. * 返 回 值  :
  60. * 调用关系  :DMA接收的数据缓存在USART接收中,释放DMA继续接收
  61. * 其    它  :
  62. *****************************************************************************/
  63. void UsartReceive_IDLE(UART_HandleTypeDef *huart)
  64. {
  65.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))
  66.         {
  67.               if(huart->Instance == huart2.Instance)//判断是否为串口2
  68.                 {
  69.                  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //是否为空闲中断
  70.                    {
  71.                    __HAL_UART_CLEAR_IDLEFLAG(&huart2);                     //清除空闲中断
  72.                    HAL_UART_DMAStop(&huart2);                                                     //停止本次DMA传输
  73.             Usart1type.UsartDMAReclen  = USART1_DMA_REC_SIE - huart2.hdmarx->Instance->NDTR;   //计算本次传输数据长度
  74.                                                 if(Usart1type.UsartReclen>0)
  75.                                                  {
  76.                                                         memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartReclen], Usart1type.Usart1DMARecBuffer, Usart1type.UsartDMAReclen);
  77.                                                         Usart1type.UsartReclen+=Usart1type.UsartDMAReclen;
  78.                                                  }
  79.                                                 else if(Usart1type.UsartReclen>USART1_REC_SIE)//如果串口接收数据溢出,从0开始记录
  80.                                                  {
  81.                                                          Usart1type.UsartReclen=0;
  82.                                                  }
  83.                                                 else
  84.                                                  {
  85.                                                         memcpy(Usart1type.Usart1RecBuffer, Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMAReclen);
  86.                                                         Usart1type.UsartReclen=Usart1type.UsartDMAReclen;
  87.                                                  }                                       
  88.                                                 memset(Usart1type.Usart1DMARecBuffer, 0x00, sizeof(Usart1type.Usart1DMARecBuffer ));//DMA数据清零                                                                                
  89.                                                 Usart1type.UsartRecFlag=1;//空闲标志位置1
  90.                         HAL_UART_Receive_DMA(&huart2, Usart1type.Usart1DMARecBuffer, USART1_DMA_REC_SIE);//重新打开DMA
  91.                                         }               
  92.                   }
  93.         }
  94. }
  95. /*****************************************************************************
  96. * 函 数 名  : Analysis_Serial_Data
  97. * 负 责 人  : by
  98. * 创建日期  : 2020年8月26日
  99. * 函数功能  : 串口接收数据直接打印
  100. * 输入参数  : void  无
  101. * 输出参数  : 无
  102. * 返 回 值  : void
  103. * 调用关系  :
  104. * 其    它  :
  105. *****************************************************************************/
  106. void Analysis_Serial_Data(void)
  107. {
  108.                  if(Usart1type.UsartRecFlag)
  109.                  {                                 
  110.                          Usart1SendData_DMA(Usart1type.Usart1RecBuffer,Usart1type.UsartReclen);        
  111.                          Usart1type.UsartRecFlag=0;
  112.                          Usart1type.UsartReclen=0;//测试处理为将全部数据进行打印处理,若需解析,可将解析长度进行减少,多次处理         
  113.                  }
  114. }
  115. /*****************************************************************************
  116. * 函 数 名  : fputc
  117. * 负 责 人  : by
  118. * 创建日期  : 2020年8月26日
  119. * 函数功能  : 串口2 printf重定义
  120. * 输入参数  : printf(d%/s%/%c,a)
  121. * 输出参数  : 无
  122. * 返 回 值  :
  123. * 调用关系  :
  124. * 其    它  :   
  125. *****************************************************************************/
  126. #ifdef __GNUC__

  127.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
  128. set to 'Yes') calls __io_putchar() */
  129. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  130. #else

  131.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  132. #endif /* __GNUC__ */
  133.         
  134. PUTCHAR_PROTOTYPE
  135. {
  136.         HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
  137.         return ch;
  138. }


  139. /* USER CODE END 1 */
  140. DMA发送函数,网上给的教程while是用来保证DMA收发节奏的,节奏错误会出现死循环情况,给注释掉了。。。。

  141. //while(Usart1type.dmaSend_flag == USART_DMA_SENDING);  
  142.     Usart1type.dmaSend_flag = USART_DMA_SENDING;
复制代码


6.3  主函数,只用DMA通讯只需添加EnableUsart_IT();/*串口初始化*/,即可,对应usart.c里的函数
  1.   /* USER CODE BEGIN 2 */
  2.   HAL_TIM_Base_Start_IT(&htim3);/*使能定时器3中断***/
  3.   HAL_TIM_Base_Start_IT(&htim2);/*使能定时器2中断*/
  4.   HAL_CAN_Start(&hcan1);/*can初始化*/
  5.   HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);                        
  6.   EnableUsart_IT();/*串口初始化*/
  7.   CAN_User_Init(&hcan1);        
  8.   /* USER CODE END 2 */
复制代码

循环,对应数据输出

  1. /* USER CODE BEGIN WHILE */
  2.   while (1)
  3.   {               
  4.      Analysis_Serial_Data();
  5.     /* USER CODE END WHILE */

  6.     /* USER CODE BEGIN 3 */
  7.   }
  8.   /* USER CODE END 3 */
  9. }
  10. 7
复制代码

、实验结果,间隔10ms,连续发送,未出现丢帧,或其他错误

2020090115084313.png



收藏 评论0 发布时间:2021-12-14 10:07

举报

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