1.DMA介绍
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。
DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
2.具体配置
(1)串口2配置
step1 点击USATR2
step2 设置MODE为异步通信(Asynchronous)
step3 基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1 接收和发送都使能
step4 GPIO引脚自动设置 USART1_RX/USART_TX
step5 NVIC Settings 一栏使能接收中断
step1 点击DMASettings 点击 Add 添加通道
step2 选择USART_RX USART_TX 传输速率设置为中速
step3 DMA传输模式为正常模式
step4 DMA内存地址自增,每次增加一个Byte(字节)
3.代码编写
(1) usart.c 部分修改
volatile uint8_t rx_len = 0; //接收一帧数据的长度
volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志
uint8_t rx_buffer[100]={0}; //接收数据缓存数组
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
//添加代码
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); //使能IDLE中断
HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);
}
(2) usart.h 部分修改
#define BUFFER_SIZE 100
extern volatile uint8_t rx_len ; //接收一帧数据的长度
extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志
extern uint8_t rx_buffer[100]; //接收数据缓存数组
(3)main.c修改
/*
*********************************************************************************************************
* 函 数 名: DMA_Usart_Send
* 功能说明: 串口发送功能函数
* 形 参: buf,len
* 返 回 值: 无
*********************************************************************************************************
*/
void DMA_Usart_Send(uint8_t *buf,uint8_t len)//串口发送封装
{
if(HAL_UART_Transmit_DMA(&huart2, buf,len)!= HAL_OK) //判断是否发送正常,如果出现异常则进入异常中断函数
{
Error_Handler();
}
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*
HAL_GPIO_TogglePin(GPIOI,GPIO_PIN_6);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_5);
HAL_Delay(500);
*/
if(recv_end_flag == 1) //接收完成标志
{
DMA_Usart_Send(rx_buffer, rx_len);
rx_len = 0;//清除计数
recv_end_flag = 0;//清除接收结束标志位
memset(rx_buffer,0,rx_len);
}
HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
(3) stm32f4xx_it.c修改
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除标志位
HAL_UART_DMAStop(&huart2); //
temp = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中未传输的数据个数
rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
4.测试结果
发送和接收正常
5.源码和工程下载链接
https://download.csdn.net/download/qyx635804080/69486446