DMA-搬运工

DMA-搬运工
1.
DMA(Direct Memory Access)直接内存访问,可以把数据从一个地方传输到另一个地方,不会占用我们的cpu。
CPU根据代码内容执行指令,
这些众多指令中,有的用于计算、有的用于控制程序、有的用于转移数据等。其中转移数据的指令,尤其
是转移大量数据,会占用大量CPU。如果是把外设A的数据,传给外设B,这种情况其实不需要CPU一直参
与,只需在A、B之间创建个通道,让它们自己传输即可。这就是DMA设计的目的,减少大量数据转移指令。
在这里插入图片描述

DMA主要实现将A处的数据直接搬运到B处,这里的A、B可以是内存(内/外部SRAM等),也可以是外
设(UART、I2C、SPI、ADC等),因此所有的场景如下三种:
 内存到外设
 外设到内存
 内存到内存

DMA1有7个通道,DMA2有5个 通道,总计12个通道。
可以把DMA分为三部分。
后,DMA控制器根据通道优先级依次处理请求,当轮到该外设时,返回应答信号给该外设,该外设收到
应答信号,释放该请求,进行DMA数据传输,直至DMA传输结束;
②DMA通道:不同的外设,向不同DMA的不同通道发送请求,如图 20.1.2 和图 20.1.3 所示。比如ADC1
想使用DMA,应向DMA1的通道1发送请求。DMA1的通道1,可以接收多个外设的请求(ADC1、TIM2_CH3、
TIM4_CH1),但同一时间只能接收一个;
③DMA优先级:当多个DMA通道,同时发来请求时,获取软件配置DMA_CCRx寄存器设置的优先级,
依次响应。当软件配置优先级相同时,硬件优先级高的(通道编号小的)优先响应。有DMA2的产品中,DMA1 的优先级高于DMA2。
在这里插入图片描述
在这里插入图片描述

内存到内存所有通道都可以用。

在这里插入图片描述

多个DMA同时请求:
1.软件阶段:DMA_CCRx DMA通道配置寄存器PL->设置通道优先级
2.硬件阶段: 通道编号小的优先级大,DMA1优先级大于DMA2

相关寄存器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

void DCMI_DMA_Init(void)
{ 
	DMA_InitTypeDef  DMA_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
	DMA_DeInit(DMA2_Stream1);
	while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置 
	
	DMA_InitStructure.DMA_Channel = DMA_Channel_1;  //通道1 DCMI通道 
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&DCMI->DR;//外设地址为:DCMI->DR  摄像头
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&LCD->LCD_RAM;//DMA 存储器0地址 lcd
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式 搬运数据:摄像头->lcd
	DMA_InitStructure.DMA_BufferSize = 10;//数据传输量 
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//存储器增量模式 关闭
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ;//存储器数据长度 16bit 
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式 
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式        
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO 
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
	DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA Stream
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel=	DMA2_Stream1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、	
} 

//DCMI,启动传输

void DCMI_Start(void)
{ 
	LCD_Scan_Dir(U2D_L2R);	//U2D_L2R	   //扫描方式从上到下,从左到右,一般模式	
	LCD_Set_Window(0,0,320,240); //LCD设置显示窗口,如果改变了分辨率,这里需要更改
	LCD_SetCursor(0,0); //设置光标 
	LCD_WriteRAM_Prepare();	//开始写入GRAM
	DMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2,Stream1 
	DCMI_CaptureCmd(ENABLE);//DCMI捕获使能  
}
//DCMI,关闭传输
void DCMI_Stop(void)
{ 
	DCMI_CaptureCmd(DISABLE);//DCMI捕获使关闭	
	while(DCMI->CR&0X01);		//等待传输结束  	
	DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
} 
//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
	if(DCMI_GetITStatus(DCMI_IT_LINE)==SET)//捕获到行
	{
		DCMI_ClearITPendingBit(DCMI_IT_LINE);//清除中断	
		ov_frame++;
	}
	
} 
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴凯你在想啥呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值