半小时搞懂STM32面经知识——DMA

1.DMA

1.1 什么是DMA?

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输
CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
在这里插入图片描述
比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理

1.2 DMA的传输的四种情况?

1.外设到内存
2.内存到外设
3.内存到内存
4.外设到外设

在这里插入图片描述
Flash只读不写;

1.3 DMA的传输参数

数据传输,首先需要的是
1.数据的源地址
2.数据传输位置的目标地址
3.传递数据多少的数据传输量
4.传输模式(多少次,是否地址自增)

当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输,也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。

1.4 STM32多少个DMA资源?

对于大容量的STM32芯片有2个DMA控制器,两个DMA控制器,DMA1有7个通道,DMA2有5个通道。

1.5 DMA的框图

在这里插入图片描述
传输计数器:自减,记录运转次数
自动重装器:减到0是否重装
硬件触发:与外设相关的转运
软件触发:适用于存储器到存储器,存储器直接软件启动
开关控制:开启DMA运转的三大条件:1.传输计数器>0;2.触发源有信号;3.DMA使能;
在这里插入图片描述
将DataA转到DataB,外设地址为数组地址,存储器地址为DataB首地址,宽度按照8个字节传输,两地址都自增,传输计数器给7,无需自动装载,使用软件触发,调用DMA_cmd();
在这里插入图片描述
外设地址给ADC_DR地址,存储器地址在SRAM中定一个数组ADCValue,以16位半字传输;

1.6 DMA的工作流程

如果没有DMA,CPU传输数据还要以内核作为中转站,比如要将ADC采集的数据转移到到SRAM中,这个过程是这样的:
①内核通过DCode经过总线矩阵协调,从获取AHB存储的外设ADC采集的数据。
②然后内核再通过DCode经过总线矩阵协调把数据存放到内存SRAM中。

在这里插入图片描述
如果有DMA,
①DMA传输时外设对DMA控制器发出请求。
②DMA控制器收到请求,触发DMA工作。
③DMA控制器从AHB外设获取ADC采集的数据,存储到DMA通道中
④DMA控制器的DMA总线与总线矩阵协调,使用AHB把外设ADC采集的数据经由DMA通道存放到SRAM中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与。

在这里插入图片描述
在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。DMA传输结束,如果有更多的请求时,外设可以启动下一个周期。

总之,每次DMA传送由3个操作组成:
1.从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
2.存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;
3.执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

1.7 DMA传输方式

①正常模式。
②循环传输模式。

1.8 DMA的初始化配置

DMA寄存器配置流程

  1. DMA初始化:首先,需要初始化DMA控制器和选择合适的DMA通道。可以使用相关的库函数来进行初始化。
  2. 配置DMA通道:然后,配置DMA通道的源和目的地址、数据长度以及传输模式等参数。
  3. 启动DMA传输:配置完成后,启动DMA传输,开始高速数据传输。
  4. DMA中断处理:如果需要在传输完成后进行相应的处理,可以配置DMA中断,并在中断处理函数中实现后续操作。

①DMA初始化配置

void dma_init()
{
 
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

/*DMA配置*/
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;//串口数据寄存器地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff; //内存地址(要传输的变量的指针)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向(从内存到外设)
DMA_InitStructure.DMA_BufferSize = 500; //传输内容的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte ; //外设数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte ; //内存数据单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //DMA模式:一次传输,循环
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium ; //优先级:高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存的传输
 
DMA_Init(DMA1_Channel4, &DMA_InitStructure); //配置DMA1的4通道
DMA_Cmd(DMA1_Channel4,ENABLE);
DMA_SetCurrDataCounter(DMA_CH4,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//配置DMA发送完成后产生中断
 
}

②DMA中断

void DMA1_Channel4_IRQHandler(void)
{
	if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET)
	{
		DMA_ClearFlag(DMA1_FLAG_TC4);
	}
}

③main函数

#define SEND_BUF_SIZE 500	//发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.
 
u8 SendBuff[SEND_BUF_SIZE];	//发送数据缓冲区
const u8 TEXT_TO_SEND[]={"STM32F1 DMA 串口实验"};
uint16_t i;
int main(void)
{	   
	uart_init(115200);	 	//串口初始化为115200
	for(i=0;i<500;i++)
	{
		SendBuff[i] =0xaf;
	}	
	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);  //使能串口dma传输 
	while(1);
}

DMA 控制器驱动程序的大概实现?
1.初始化DMA控制器:使用STM32提供的库函数或寄存器配置,初始化DMA控制器的相关寄存器,设置DMA通道、传输模式、数据传输方向、传输大小等参数。
2.分配和映射缓冲区:分配一块内存作为发送缓冲区,并将其映射到物理内存地址空间。
3.将数据写入发送缓冲区:将待发送的数据写入分配的发送缓冲区中。
4.配置DMA传输:使用STM32提供的库函数或寄存器,将发送缓冲区的起始地址和数据长度等信息提供给DMA控制器,配置DMA传输的相关寄存器。
5.配置外设:配置外设(如UART、SPI等),使其与DMA通道关联,以便DMA可以直接从发送缓冲区读取数据,并将其发送到外设。
6.启动DMA传输:使用STM32提供的库函数或寄存器,发出启动DMA传输的命令,使DMA控制器开始执行数据的传输操作。
7.DMA传输完成处理:当DMA传输完成后,DMA控制器会生成一个中断信号通知CPU。可以通过配置中断处理函数(如DMA传输完成中断)来处理传输完成的事件,进行相应的操作,如清理发送缓冲区、更新数据等。
进行 DMA 传输的时候如何解决缓存一致性问题?
中断和DMA在嵌入式系统中的应用场景有何不同?
DMA的工作流程?
ADC采集方式,为什么使用DMA+中断?
答:减少CPU负载,提升效率,CPU只需要处理中断,在中断处理函数中处理采集到的数据,不需要实时轮询ADC转换结束的状态。
DMA为什么能提高效率?
答:无须CPU干预,节省了CPU的资源

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值