2021-11-08


一、DMA的基本介绍

DMA,全称Direct Memory Access,即直接存储器访问。

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,

CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?

因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,

DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。

二、通过cubemx实现DMA中断通信

1、配置管脚

芯片为stm32f103c8tx,需要使用的管脚有pa9(usart1_tx),pa10(usart1_rx),以及一个控制led灯亮灭的管脚(通过DMA中断),我选择的是pa5。

2.配置usart

usart1配置如下:

在这里插入图片描述

波特率为115200,8位数据位,1位停止位,无校验位。

3.DMA及其他配置

在DMA Setting中,点击add,即可自动添加可以启用的DMA通道,然后启用nvic,rcc设置为使用外部时钟,时钟配置根据自己使用的芯片参数进行配置。设置好项目位置和名称,生成代码然后打开项目。

4.相关用户代码配置。

在main函数之前创建全局变量Senbuff数组,存放接收的数据,定义count和flag,保存串口接收数据状态,在while循环之前加以下代码

 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能串口空闲中断
  HAL_UART_Receive_DMA(&huart1, Senbuff,len);
  //开启DMA接收,不加此自启后接收一次空字符

之后,自定义中断处理函数。函数如下

void MX_RXCallBack(UART_HandleTypeDef *huart)
{
    
    
  uint8_t  tmp_flag,temp;
  tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
  if((tmp_flag != RESET))
  {
    
    
    __HAL_UART_CLEAR_FLAG(&huart1,tmp_flag);
    HAL_UART_DMAStop(&huart1);
    temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    HAL_UART_Receive_DMA(&huart1,Senbuff,len);
    count= len - temp;
  }  
  flag = 1;
  //led灯闪烁一次
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
  HAL_Delay(100);
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
}

while循环中函数代码如下:

while(1)
{
    
    
	if(flag){
    
    
		HAL_UART_Transmit_DMA(&huart1,Senbuff,len);
		HAL_Delay(100);
		//重置数据接收区
		flag=0;
		memset(Senbuff,0,count);
	}
}

测试与预期一致。
请添加图片描述


猜你喜欢

转载自blog.csdn.net/weixin_45747542/article/details/121213674