收藏官网首页
查看: 20619|回复: 1

STM32CubeMX 使用DMA 实现不定长数据收发

50

主题

94

帖子

2135

积分

金牌会员

Rank: 6Rank: 6

积分
2135
跳转到指定楼层
楼主
发表于 2017-11-27 17:13:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
校园创客福利
这里教程是选择的STM32F407。STM32F103也测试过。
1.首先选择串口,选择异步通信。

2.添加DMA

3.打开中断

4.生成代码,生成代码选择了每个外设单独使用.c/.h

5.我使用的是Keil5。打开工程,首先注释掉dma.c里的DMA接收中断,因为不需要DMA接收中断,DMA发送中断是需要的。(dma.c)

[cpp] view plain copy


  • void MX_DMA_Init(void)   
  • {  
  •   /* DMA controller clock enable */  
  •   __HAL_RCC_DMA2_CLK_ENABLE();  
  •   
  •   /* DMA interrupt init */  
  •   /* DMA2_Stream0_IRQn interrupt configuration */  
  •   HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 2, 0);  
  •   HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);  
  •   /* DMA2_Stream2_IRQn interrupt configuration */  
  • //  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);  
  • //  HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);  
  •   /* DMA2_Stream7_IRQn interrupt configuration */  
  •   HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 1, 0);  
  •   HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);  
  •   
  • }  

6.在usart.h文件里定义串口接收数据类型我是如下定义的(usart.h)

[cpp] view plain copy


  • /* USER CODE BEGIN Private defines */  
  • #define RECEIVELEN 1024  
  • #define USART_DMA_SENDING 1//发送未完成  
  • #define USART_DMA_SENDOVER 0//发送完成  
  • typedef struct  
  • {  
  • uint8_t receive_flag:1;//空闲接收标记  
  • uint8_t dmaSend_flag:1;//发送完成标记  
  • uint16_t rx_len;//接收长度  
  • uint8_t usartDMA_rxBuf[RECEIVELEN];//DMA接收缓存  
  • }USART_RECEIVETYPE;  
  •    
  • extern USART_RECEIVETYPE UsartType1;  
  •   
  •   
  • /* USER CODE END Private defines */  

7.然后在usart.c里需要添加空闲中断处理函数,以及DMA发送函数等。(usart.c)
首先定义串口数据类型:

[cpp] view plain copy


  • /* USER CODE BEGIN 0 */  
  •   
  • USART_RECEIVETYPE UsartType1;  
  •   
  • /* USER CODE END 0 */  


然后定义空闲中断处理函数和DMA发送函数

[cpp] view plain copy


  • /* USER CODE BEGIN 1 */  
  • #ifdef __GNUC__  
  •   
  •   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
  • set to 'Yes') calls __io_putchar() */  
  • #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
  • #else  
  •   
  •   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
  • #endif /* __GNUC__ */  
  •       
  • PUTCHAR_PROTOTYPE  
  • {  
  •     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);  
  •     return ch;  
  • }  
  •   
  • //DMA发送函数  
  • void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  
  • {  
  •     while(UsartType1.dmaSend_flag == USART_DMA_SENDING);  
  •     UsartType1.dmaSend_flag = USART_DMA_SENDING;  
  •     HAL_UART_Transmit_DMA(&huart1, pdata, Length);  
  • }  
  •   
  • //DMA发送完成中断回调函数  
  • void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  
  • {  
  •      __HAL_DMA_DISABLE(huart->hdmatx);  
  •     UsartType1.dmaSend_flag = USART_DMA_SENDOVER;  
  • }  
  •   
  • //串口接收空闲中断  
  • void UsartReceive_IDLE(UART_HandleTypeDef *huart)  
  • {  
  •     uint32_t temp;  
  •   
  •     if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  
  •     {   
  •         __HAL_UART_CLEAR_IDLEFLAG(&huart1);  
  •         HAL_UART_DMAStop(&huart1);  
  •         temp = huart1.hdmarx->Instance->NDTR;  
  •         UsartType1.rx_len =  RECEIVELEN - temp;   
  •         UsartType1.receive_flag=1;  
  •         HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);  
  •     }  
  • }  
  •   
  • /* USER CODE END 1 */  



[cpp] view plain copy


  • </pre><p></p><pre>  

8.在中断文件里添加(当然,上面的空闲中断处理函数需要**)(stm32f4xxit.c)[cpp] view plain copy


  • void USART1_IRQHandler(void)  
  • {  
  •   /* USER CODE BEGIN USART1_IRQn 0 */  
  •     UsartReceive_IDLE(&huart1);  
  •   /* USER CODE END USART1_IRQn 0 */  
  •   HAL_UART_IRQHandler(&huart1);  
  •   /* USER CODE BEGIN USART1_IRQn 1 */  
  •   
  •   /* USER CODE END USART1_IRQn 1 */  
  • }  


9.主函数里,打开空闲中断,初始化DMA接收

[cpp] view plain copy


  • /* USER CODE BEGIN 2 */  
  •     HAL_UART_Receive_DMA(&huart1, UsartType1.usartDMA_rxBuf, RECEIVELEN);  
  •     __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  
  •   /* USER CODE END 2 */  


10.然后就可以在while(1)里处理数据了

[cpp] view plain copy


  • /* Infinite loop */  
  •   /* USER CODE BEGIN WHILE */  
  •       
  •   while (1)  
  •   {  
  •         if(UsartType1.receive_flag)//如果产生了空闲中断  
  •         {  
  •             UsartType1.receive_flag=0;//清零标记  
  •             Usart1SendData_DMA(UsartType1.usartDMA_rxBuf,UsartType1.rx_len);//串口打印收到的数据。  
  •         }  
  •   /* USER CODE END WHILE */  
  •   
  •   /* USER CODE BEGIN 3 */  
  •          
  •   }  
  •   /* USER CODE END 3 */  

IoT软件平台

562

主题

1222

帖子

8127

积分

版主

Rank: 7Rank: 7Rank: 7

积分
8127
沙发
发表于 2017-11-28 10:54:21 | 只看该作者
不定长数据收发和定长数据收发,两者有什么区别和特点
1、机智云QQ群: 287087942
机智云爱好者-APP开发群: 599735135
QQ群目前非常活跃,欢迎大家参与进来,交流,讨论,答疑,解惑~~
2、机智云微信公众号: 机智云 gizwits /   机智云智能宠物屋go-kit
关注机智云Gizwits官方公众号随时掌握最新资讯和活动信息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表