Bootstrap

STM32-cubemx-DMA-UART-笔记(振兴中华)

 原文章:【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_Z小旋的博客-CSDN博客_hal dma

#include <string.h>
memset(rx_buffer,0,rx_len);//清空数组rx_buffer,长度是rx_len

通过DMA发送,串口号、发啥数据、多长的数据:
HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);

判断一下是不是发完了:“DMA1_Channel4”在DMA.C文件最后面可以看到,
或者是从CUBE的dma配置界面看到TX的通道号:
while(DMA1_Channel4->CNDTR !=0); 




c文件定义:定义你这数据多长,中断中接收完了的标志位,你接收数据用的数组
volatile uint8_t rx_len = 0;				//接收一帧数据的长度 main和中断函数使用 
volatile uint8_t recv_end_flag = 0;		    //一帧数据接收完成标志 main和中断函数使用
uint8_t rx_buffer[100] = {0};				//接收数据缓存数组 数据寸这里
h文件声明:声明一下上面的东西,方便别人用
#define BUFFER_SIZE  100   					//计数用,判断数组长度和下面那个一样要
extern volatile uint8_t rx_len;				//接收一帧数据的长度
extern volatile uint8_t recv_end_flag;		//一帧数据接收完成标志
extern uint8_t rx_buffer[BUFFER_SIZE];		//接收数据缓存数组

中断函数:看一下数据接收完了,清除标志位停止DMA然后判断数据长度,立中断中接收完了的标志位FLAG
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET))//idle标志被置位
{ 
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除IDLE标志位
HAL_UART_DMAStop(&huart1); //停止DMA传输,防止叠加数据 在main处理函数之后在给他打开
rx_len =  BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); 
recv_end_flag = 1;//中断中接收完了的标志位挂起
}

if(recv_end_flag == 1)  //中断中接收完了的标志位在main函数中的while函数中检测到了
{//执行串口数据处理函数
HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);	//串口1发送这个数组,发送长度rx_len是中断函数中计算出来的
recv_end_flag = 0;//清除中断接收完了的标志位
while(DMA1_Channel4->CNDTR !=0); //看看是不是发完了
memset(rx_buffer,0,rx_len);//发完了数据再清空数组
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}

 自动生成的main.c文件中添加如下代码:

因为下面用到了memset函数,所以在头文件处添加:#include <string.h>,然后填写下面代码段:
while (1)
  {
     if(recv_end_flag == 1)  //接收完成标志 
		{
			HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);	//串口发送
			recv_end_flag = 0;                 //清除接收结束标志位
			while(DMA1_Channel4->CNDTR !=0);   //从CUBEMX里面找 串口发送完成
			memset(rx_buffer,0,rx_len);        //清空
			rx_len = 0;                        //清除计数
            HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
		}
  }

 自动生成的usart.c文件中添加如下代码:

/* USER CODE BEGIN 0 */
volatile uint8_t rx_len = 0;			//接收一帧数据的长度 main和中断函数使用 
volatile uint8_t recv_end_flag = 0;		//一帧数据接收完成标志 main和中断函数使用
uint8_t rx_buffer[100] = {0};			//接收数据缓存数组 数据寸这里
/* USER CODE END 0 */

void MX_USART1_UART_Init(void)//该函数中添加下面这俩代码
{
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//使能IDLE中断
	HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//开启DMA接收
}

 自动生成的usart.h文件中添加如下代码:

/* USER CODE BEGIN Private defines */
#define BUFFER_SIZE  100   				//计数用,判断数组长度和下面那个一样要
extern volatile uint8_t rx_len;			//接收一帧数据的长度
extern volatile uint8_t recv_end_flag;	//一帧数据接收完成标志
extern uint8_t rx_buffer[BUFFER_SIZE];	//接收数据缓存数组
/* USER CODE END Private defines */

//usart.c和.ch文件中很容易看出来,仅仅是添加了几个变量而已,至于为啥放到usart文件中,是为了分类管理,你可以自己建自己的文件放进去。

自动生成的stm32f1xx_it.c文件中添加如下代码: 

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

	if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET)) //idle标志被置位
	{ 
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除IDLE标志位
		HAL_UART_DMAStop(&huart1);         //停止DMA传输,防止叠加数据
		rx_len =  BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //求存了多少数
		recv_end_flag = 1;//接收了数据
	}
	
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* USER CODE END USART1_IRQn 1 */
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;