STM32F7 DMA驱动

之前已经写过了,这次做的灵活一些,例子看我后面发的SAI驱动,使用的是DMA双缓冲模式。

//DMA外设结构
static const  DMA_TypeDef * const DMA_TYPE_BUFF[2] = {DMA1, DMA2};
static const DMA_Stream_TypeDef *DMA1_Stream[8] = {DMA1_Stream0, DMA1_Stream1, DMA1_Stream2, DMA1_Stream3, DMA1_Stream4, DMA1_Stream5, DMA1_Stream6, DMA1_Stream7};
static const DMA_Stream_TypeDef *DMA2_Stream[8] = {DMA2_Stream0, DMA2_Stream1, DMA2_Stream2, DMA2_Stream3, DMA2_Stream4, DMA2_Stream5, DMA2_Stream6, DMA2_Stream7};
	


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//2020-02-20 新标准接口

/*************************************************************************************************************************
* 函数			:	void DMA_Config(DMAxSx_CH_TYPE DMAxSx_Ch, DAM_CONFIG *pConfig)
* 功能			:	DMA配置
* 参数			:	DMAxSx_Ch:DMA通道选择;pConfig:配置,见DAM_CONFIG
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2020-02-20
* 最后修改时间 	: 	2020-02-20
* 说明			: 	
*************************************************************************************************************************/
void DMA_Config(DMAxSx_CH_TYPE DMAxSx_Ch, DAM_CONFIG *pConfig)
{
	u8 Stream,ch;
	DMA_Stream_TypeDef *DMA_Stream;
	DMA_TypeDef *DMAx;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	ch = DMAxSx_Ch&0xff;
	if((ch > 7) || (Stream > 7))											//通道或流超出了范围
	{
		return;
	}
	if((DMAxSx_Ch >> 16)&0x01)												//DMA2
	{
		SYS_DeviceClockEnable(DEV_DMA2, TRUE);								//使能DMA2时钟
		DMA_Stream = (DMA_Stream_TypeDef *)DMA2_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	else //DMA1
	{
		SYS_DeviceClockEnable(DEV_DMA1, TRUE);								//使能DMA1时钟
		DMA_Stream = (DMA_Stream_TypeDef *)DMA1_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	
	//开始配置
	DMA_Stream->CR = 0;														//禁止数据流,才能进行后面的设置
	DMA_Stream->CR |= ch<<25;												//设置通道
	DMA_Stream->CR |= (pConfig->Mem_BurstSize & 0x03)<<23;					//存储器突发传输配置
	DMA_Stream->CR |= (pConfig->Per_BurstSize & 0x03)<<21;					//外设突发传输配置
	if(pConfig->isDoubleBuffer)												//使能双缓冲模式
	{
		DMA_Stream->CR |=  1<<18;
	}
	DMA_Stream->CR |= (pConfig->PrioLevel & 0x03)<<16;						//优先级设置
	if(!pConfig->isPerIncPsizeAuto)											//外设地址的偏移量与 PSIZE 相关
	{
		DMA_Stream->CR |= 1<<15;											//用于计算外设地址的偏移量固定为 4(32 位对齐)。
	}
	DMA_Stream->CR |= (pConfig->Mem_Size & 0x03)<<13;						//存储器数据大小设置
	DMA_Stream->CR |= (pConfig->Pre_Size & 0x03)<<11;						//外设数据大小设置
	if(pConfig->isMemInc)
	{
		DMA_Stream->CR |= 1<<10;											//存储器地址递增模式
	}
	if(pConfig->isPerInc)
	{
		DMA_Stream->CR |= 1<<9;												//外设地址递增模式
	}
	if(pConfig->isCircMode)
	{
		DMA_Stream->CR |= 1<<8;												//循环模式
	}
	DMA_Stream->CR |= (pConfig->DataTranDir & 0x03)<<6;						//数据传输方向
	if(pConfig->isPreFlowCtrl)
	{
		DMA_Stream->CR |= 1<<5;												//外设是流控设备
	}
	if(pConfig->isEnableTranComplInt)
	{
		DMA_Stream->CR |= 1<<4;												//使能完成中断
	}
	DMA_Stream->NDTR = pConfig->TranDataCount;								//传输的数据项数-外设到存储器是流控无需设置长度
	DMA_Stream->PAR = pConfig->PerAddr;										//外设地址
	DMA_Stream->M0AR = pConfig->Mem0Addr;									//存储器0地址
	DMA_Stream->M1AR = pConfig->Mem0Addr;									//存储器1地址
	DMA_Stream->FCR = 0;
	if(!pConfig->isDirectMode)	
	{
		DMA_Stream->FCR |= 1 << 2;											//禁止直接模式
	}		
	DMA_Stream->FCR |= (pConfig->FIFO_Thres & 0x03)<<0;						//FIFO阈值选择
	//必须清除中断标记,否则DMA可能会停止工作
	DMA_ClearIntStatus(DMAxSx_Ch, DMA_INT_ALL);
	
	if(pConfig->isEnableStream)
	{
		DMA_Stream->CR |= 1<<0;												//使能流,开始传输
	}		
	//uart_printf("DMA_Stream->NDTR:%X\r\n",DMA_Stream->NDTR);
	//uart_printf("DMA_Stream->NDTR:%X\r\n",DMA_Stream->NDTR);
	//uart_printf("DMA_Stream->NDTR:%X\r\n",DMA_Stream->NDTR);
}



/*************************************************************************************************************************
* 函数	:			void DMA_StartTrans(DMAxSx_CH_TYPE DMAxSx_Ch, u32 Mem0Addr, u32 Mem1Addr, u16 TranDataCount)
* 功能	:			启动DMA 传输
* 参数	:			DMAxSx_Ch:DMA通道选择;Mem0Addr:内存地址0,Mem1Addr:内存地址1(双缓冲模式下有效);TranDataCount:传输数据数量
* 返回	:			无
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2020-02-20
* 最后修改时间 : 	2020-02-02
* 说明	: 			启动传输,请先调用DMA_Config对当前通道进行配置
*************************************************************************************************************************/  
void DMA_StartTrans(DMAxSx_CH_TYPE DMAxSx_Ch, u32 Mem0Addr, u32 Mem1Addr, u16 TranDataCount)
{
	u8 Stream,ch;
	DMA_Stream_TypeDef *DMA_Stream;
	DMA_TypeDef *DMAx;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	ch = DMAxSx_Ch&0xff;
	if((ch > 7) || (Stream > 7))											//通道或流超出了范围
	{
		return;
	}
	if((DMAxSx_Ch >> 16)&0x01)												//DMA2
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA2_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	else //DMA1
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA1_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	
	DMA_Stream->CR &= ~BIT0;												//关闭数据流	
	DMA_Stream->NDTR = TranDataCount;										//传输的数据项数
	DMA_Stream->M0AR = Mem0Addr;											//存储器0地址
	DMA_Stream->M1AR = Mem1Addr;											//存储器1地址	
	//必须清除中断标记,否则DMA可能会停止工作
	DMA_ClearIntStatus(DMAxSx_Ch, DMA_INT_ALL);
	
	DMA_Stream->CR |= 1<<0;													//使能流,开始传输
}

/*************************************************************************************************************************
* 函数	:			void DMA_StopTrans(DMAxSx_CH_TYPE DMAxSx_Ch)
* 功能	:			关闭 DMA 传输
* 参数	:			DMAxSx_Ch:DMA通道选择
* 返回	:			无
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2020-02-20
* 最后修改时间 : 	2020-02-02
* 说明	: 			
*************************************************************************************************************************/  
void DMA_StopTrans(DMAxSx_CH_TYPE DMAxSx_Ch)
{
	u8 Stream,ch;
	DMA_Stream_TypeDef *DMA_Stream;
	DMA_TypeDef *DMAx;
	u8 retry = 10;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	ch = DMAxSx_Ch&0xff;
	if((ch > 7) || (Stream > 7))											//通道或流超出了范围
	{
		return;
	}
	if((DMAxSx_Ch >> 16)&0x01)												//DMA2
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA2_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	else //DMA1
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA1_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	
	DMA_Stream->CR &= ~BIT0;												//关闭数据流	
	while((DMA_Stream->CR & BIT0) && retry)									//等待数据流关闭成功
	{
		retry --;
		SYS_DelayMS(1);
	}
	//必须清除中断标记,否则DMA可能会停止工作
	DMA_ClearIntStatus(DMAxSx_Ch, DMA_INT_ALL);
}



/*************************************************************************************************************************
* 函数	:			u32 DMA_GetIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch)
* 功能	:			获取DMA中断状态
* 参数	:			DMAxSx_Ch:DMA通道选择
* 返回	:			中断状态,见DMA中断定义
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2020-02-20
* 最后修改时间 : 	2020-02-02
* 说明	: 			
*************************************************************************************************************************/  
u32 DMA_GetIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch)
{
	u8 Stream;
	DMA_TypeDef *DMAx;
	u32 temp = 0;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	switch(Stream)
	{
		case 0:	//Stream 0
		{
			temp = (DMAx->LISR >> 0)&0x3F;
		}break;
		case 1:	//Stream 1
		{
			temp = (DMAx->LISR >> 6)&0x3F;
		}break;
		case 2:	//Stream 2
		{
			temp = (DMAx->LISR >> (16+0))&0x3F;
		}break;
		case 3:	//Stream 3
		{
			temp = (DMAx->LISR >> (16+6))&0x3F;
		}break;
		case 4:	//Stream 4
		{
			temp = (DMAx->HISR >> 0)&0x3F;
		}break;
		case 5:	//Stream 5
		{
			temp = (DMAx->HISR >> 6)&0x3F;
		}break;
		case 6:	//Stream 6
		{
			temp = (DMAx->HISR >> (16+0))&0x3F;
		}break;
		case 7:	//Stream 7
		{
			temp = (DMAx->HISR >> (16+6))&0x3F;
		}break;
		default: 
		{	
			temp = 0; 
		}break;
	}
	
	return temp;
}


/*************************************************************************************************************************
* 函数	:			void DMA_ClearIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch, u32 IntStatus)
* 功能	:			清除DMA中断状态
* 参数	:			DMAxSx_Ch:DMA通道选择;IntStatus:要清除的中断,见DMA中断定义
* 返回	:			无
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2020-02-20
* 最后修改时间 : 	2020-02-02
* 说明	: 			
*************************************************************************************************************************/  
void DMA_ClearIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch, u32 IntStatus)
{
	u8 Stream;
	DMA_TypeDef *DMAx;
	u32 temp;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	switch(Stream)
	{
		case 0:	//Stream 0
		{
			temp = IntStatus & 0x3F;
			DMAx->LIFCR |= temp << 0;
		}break;
		case 1:	//Stream 1
		{
			temp = IntStatus & 0x3F;
			DMAx->LIFCR |= temp << 6;
		}break;
		case 2:	//Stream 2
		{
			temp = IntStatus & 0x3F;
			DMAx->LIFCR |= temp << (16 + 0);
		}break;
		case 3:	//Stream 3
		{
			temp = IntStatus & 0x3F;
			DMAx->LIFCR |= temp << (16 + 6);
		}break;
		case 4:	//Stream 4
		{
			temp = IntStatus & 0x3F;
			DMAx->HIFCR |= temp << 0;
		}break;
		case 5:	//Stream 5
		{
			temp = IntStatus & 0x3F;
			DMAx->HIFCR |= temp << 6;
		}break;
		case 6:	//Stream 6
		{
			temp = IntStatus & 0x3F;
			DMAx->HIFCR |= temp << (16 + 0);
		}break;
		case 7:	//Stream 7
		{
			temp = IntStatus & 0x3F;
			DMAx->HIFCR |= temp << (16 + 6);
		}break;
		default : break;		
	}
}



/*************************************************************************************************************************
* 函数	:			u8 DMA_GetCurrentTargetBuffIndex(DMAxSx_CH_TYPE DMAxSx_Ch)
* 功能	:			获取双缓冲模式下当前使用的存储器缓冲区索引(0,1)
* 参数	:			DMAxSx_Ch:DMA通道选择;
* 返回	:			0:存储器0正在被使用;1:存储器1正在被使用
* 依赖	:			底层宏定义
* 作者	:			[email protected]
* 时间	:			2020-02-20
* 最后修改时间 : 	2020-02-02
* 说明	: 			仅在双缓冲模式下有效
*************************************************************************************************************************/  
u8 DMA_GetCurrentTargetBuffIndex(DMAxSx_CH_TYPE DMAxSx_Ch)
{
	u8 Stream;
	DMA_Stream_TypeDef *DMA_Stream;
	DMA_TypeDef *DMAx;
	u32 temp;
	
	DMAx = (DMA_TypeDef *)DMA_TYPE_BUFF[(DMAxSx_Ch >> 16)&0x01];			//获取DMA
	Stream = (DMAxSx_Ch >> 8)&0xff;											//获取流通道
	if(Stream > 7) return 0;
	if((DMAxSx_Ch >> 16)&0x01)												//DMA2
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA2_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	else //DMA1
	{
		DMA_Stream = (DMA_Stream_TypeDef *)DMA1_Stream[Stream];				//获取数据流 x 配置寄存器
	}
	
	if(DMA_Stream->CR & BIT19) return 1;
	else return 0;
}
/*************************************************************************************************************
 * 文件名		:	dma.c
 * 功能			:	STM32F7 DMA驱动
 * 作者			:	[email protected]
 * 创建时间		:	2016-03-13
 * 最后修改时间	:	2016-03-13
 * 详细:			几乎与STM32F4完全兼容
*************************************************************************************************************/	
#ifndef __DMA_H_
#define	__DMA_H_	   
#include "system.h"

//传输数据位宽定义
typedef enum
{
	DMA_SIZE_8BIT	=	0,
	DMA_SIZE_16BIT	=	1,
	DMA_SIZE_32BIT	=	2,
}DMA_SIZE_TYPE;



//DMA1请求映射,,高16位代表DMA1还是DMA2,高8位代表数据流,低8位位通道
typedef enum
{
	//数据流 0
	DMA1S0_SPI3_RX				=	0x000000,
	DMA1S0_I2C1_RX				=	0x000001,
	DMA1S0_TIM4_CH1				=	0x000002,
	DMA1S0_UART5_RX				=	0x000004,
	DMA1S0_UART8_TX				=	0x000005,
	DMA1S0_TIM5_CH3_TIM5_UP		=	0x000006,
	//数据流 1
	DMA1S1_SPDIF_RX_DT			=	0x000100,
	DMA1S1_I2C3_RX				=	0x000101,
	DMA1S1_TIM2_UP_TIM2_CH3		=	0x000103,
	DMA1S1_USART3_RX			=	0x000104,
	DMA1S1_UART7_TX				=	0x000105,
	DMA1S1_TIM5_CH4_TIM5_TRIG	=	0x000106,
	DMA1S1_TIM6_UP				=	0x000107,
	//数据流 2
	DMA1S2_SPI3_RX				=	0x000200,
	DMA1S2_TIM7_UP0				=	0x000201,
	DMA1S2_I2C4_RX				=	0x000202,
	DMA1S2_I2C3_RX				=	0x000203,
	DMA1S2_UART4_RX				=	0x000204,
	DMA1S2_TIM3_CH4_TIM3_UP		=	0x000205,
	DMA1S2_TIM5_CH1				=	0x000206,
	DMA1S2_I2C2_RX0				=	0x000207,
	//数据流 3
	DMA1S3_SPI2_RX				=	0x000300,
	DMA1S3_TIM4_CH2				=	0x000302,
	DMA1S3_USART3_TX			=	0x000304,
	DMA1S3_UART7_RX				=	0x000305,
	DMA1S3_TIM5_CH4_TIM5_TRIG	=	0x000306,
	DMA1S3_I2C2_RX				=	0x000307,
	//数据流 4
	DMA1S4_SPI2_TX				=	0x000400,
	DMA1S4_TIM7_UP				=	0x000401,
	DMA1S4_I2C3_TX				=	0x000403,
	DMA1S4_UART4_TX				=	0x000404,
	DMA1S4_TIM3_CH1_TIM3_TRIG	=	0x000405,
	DMA1S4_TIM5_CH2				=	0x000406,
	DMA1S4_USART3_TX			=	0x000407,
	//数据流 5
	DMA1S5_SPI3_TX				=	0x000500,
	DMA1S5_I2C1_RX				=	0x000501,
	DMA1S5_I2C4_TX				=	0x000502,
	DMA1S5_TIM2_CH1				=	0x000503,
	DMA1S5_USART2_RX			=	0x000504,
	DMA1S5_TIM3_CH2				=	0x000505,
	DMA1S5_DAC1					=	0x000507,
	//数据流 6
	DMA1S6_SPDIF_RX_CS			=	0x000600,
	DMA1S6_I2C1_TX				=	0x000601,
	DMA1S6_TIM4_UP				=	0x000602,
	DMA1S6_TIM2_CH2_TIM2_CH4	=	0x000603,
	DMA1S6_USART2_TX			=	0x000604,
	DMA1S6_UART8_RX				=	0x000605,
	DMA1S6_TIM5_UP				=	0x000606,
	DMA1S6_DAC2					=	0x000607,
	//数据流 7
	DMA1S7_SPI3_TX				=	0x000700,
	DMA1S7_I2C1_TX				=	0x000701,
	DMA1S7_TIM4_CH3				=	0x000702,
	DMA1S7_TIM2_UP_TIM2_CH4		=	0x000703,
	DMA1S7_UART5_TX				=	0x000704,
	DMA1S7_TIM3_CH3				=	0x000705,
	DMA1S7_I2C2_TX				=	0x000707,
	
	//DMA2请求映射,高16位代表DMA1还是DMA2,高8位代表数据流,低8位位通道
	//数据流 0
	DMA2S0_ADC1					=	0x010000,
	DMA2S0_ADC3					=	0x010002,
	DMA2S0_SPI1_RX				=	0x010003,
	DMA2S0_SPI4_RX				=	0x010004,	
	DMA2S0_TIM1_TRIG			=	0x010006,
	//数据流 1
	DMA2S1_SAI1_A				=	0x010100,
	DMA2S1_DCMI					=	0x010101,
	DMA2S1_ADC3					=	0x010102,
	DMA2S1_SPI4_TX				=	0x010104,
	DMA2S1_USART6_RX			=	0x010105,
	DMA2S1_TIM1_CH1				=	0x010106,
	DMA2S1_TIM8_UP				=	0x010107,
	//数据流 2
	DMA2S2_TIM8_CH1_CH2_CH3		=	0x010200,
	DMA2S2_ADC2					=	0x010201,
	DMA2S2_SPI1_RX				=	0x010203,
	DMA2S2_USART1_RX			=	0x010204,
	DMA2S2_USART6_RX			=	0x010205,
	DMA2S2_TIM1_CH2				=	0x010206,
	DMA2S2_TIM8_CH1				=	0x010205,
	//数据流 3
	DMA2S3_SAI1_A				=	0x010300,
	DMA2S3_ADC2					=	0x010301,
	DMA2S3_SPI5_RX				=	0x010302,
	DMA2S3_SPI1_TX				=	0x010303,	
	DMA2S3_SDIO					=	0x010304,
	DMA2S3_SPI4_RX				=	0x010305,
	DMA2S3_TIM1_CH1				=	0x010306,
	DMA2S3_TIM8_CH2				=	0x010307,
	//数据流 4
	DMA2S4_ADC1					=	0x010400,
	DMA2S4_SAI1_B				=	0x010401,
	DMA2S4_SPI5_TX				=	0x010402,
	DMA2S4_SAI2_A				=	0x010403,
	DMA2S4_SPI4_TX				=	0x010405,
	DMA2S4_TIM1_CH4_TRIG_COM	=	0x010406,
	DMA2S4_TIM8_CH3				=	0x010407,
	//数据流 5
	DMA2S5_SAI1_B				=	0x010500,
	DMA2S5_SPI6_TX				=	0x010501,
	DMA2S5_CRYP_OUT				=	0x010502,
	DMA2S5_SPI1_TX				=	0x010503,
	DMA2S5_USART1_RX			=	0x010504,
	DMA2S5_TIM1_UP				=	0x010506,
	DMA2S5_SPI5_RX				=	0x010507,
	//数据流 6
	DMA2S6_TIM1_CH1_CH2_CH3		=	0x010600,
	DMA2S6_SPI6_RX				=	0x010601,
	DMA2S6_CRYP_IN				=	0x010602,
	DMA2S6_SAI2_B				=	0x010603,
	DMA2S6_SDIO					=	0x010604,
	DMA2S6_USART6_TX			=	0x010605,
	DMA2S6_TIM1_CH3				=	0x010606,
	DMA2S6_SPI5_TX				=	0x010607,
	//数据流 7
	DMA2S7_SAI2_B				=	0x010700,
	DMA2S7_DCMI					=	0x010701,
	DMA2S7_HASH_IN				=	0x010702,
	DMA2S7_QUADSPI				=	0x010703,
	DMA2S7_USART1_TX			=	0x010704,
	DMA2S7_USART6_TX			=	0x010705,
	DMA2S7_TIM8_CH4_TRIG_COM	=	0x010707,
}DMAxSx_CH_TYPE;


//存储器到存储器通道定义
typedef enum
{
	//内存到内存通道,使用一些不常用的通道用内存到内存的通道
	DAM2S0_MEM					=	0x010603,
	DAM2S1_MEM					=	0x010103,
	DAM2S2_MEM					=	0x010202,
	DAM2S3_MEM					=	0x010300,
	DAM2S4_MEM					=	0x010401,
	DAM2S5_MEM					=	0x010503,
	DAM2S6_MEM					=	0x010600,
}DMA_MEM_CH;

//2020-02-20 新标准接口

//突发传输长度配置(在直接模式中,当位EN =1时这些位由硬件强制置为 0x0。)
typedef enum
{
	DMA_BURST_INCR1		=	0,	//单次传输
	DMA_BURST_INCR4		=	1,	//4个节拍传输
	DMA_BURST_INCR8		=	2,	//8个节拍传输
	DMA_BURST_INCR16	=	3,	//16个节拍传输
}DMA_BURST_TRAN_SIZE;

//优先级
typedef enum
{
	DAM_PRIO_LEVEL_0	=	0,	//优先级低
	DAM_PRIO_LEVEL_1	=	1,	//优先级中
	DAM_PRIO_LEVEL_2	=	3,	//优先级高
	DAM_PRIO_LEVEL_3	=	4,	//优先级最高
}DAM_PRIO_LEVEL;


//数据传输方向定义
typedef enum
{
	DMA_PRE_TO_MEM		=	0,	//外设到存储器
	DMA_MEM_TO_PRE		=	1,	//存储器到外设
	DMA_MEM_TO_MEM		=	2,	//存储器到存储器
}DMA_TRAN_DIR;

//FIFO阈值选择
typedef enum
{
	DMA_FIFO_THRES_1_4	=	0,	//FIFO阈值为1/4
	DMA_FIFO_THRES_1_2	=	1,	//FIFO阈值为1/2
	DMA_FIFO_THRES_3_4	=	2,	//FIFO阈值为3/4
	DMA_FIFO_THRES_FULL	=	3,	//FIFO阈值为完整容量
}DMA_FIFO_THRES;

//DMA配置
typedef struct
{
	DMA_BURST_TRAN_SIZE Mem_BurstSize;		//存储器的突发传输长度配置
	DMA_BURST_TRAN_SIZE Per_BurstSize;		//外设的突发传输长度配置
	DAM_PRIO_LEVEL PrioLevel;				//传输优先级
	DMA_SIZE_TYPE Mem_Size;					//存储器数据大小
	DMA_SIZE_TYPE Pre_Size;					//外设数据大小
	DMA_TRAN_DIR DataTranDir;				//数据传输方向
	u32 PerAddr;							//外设地址
	u32 Mem0Addr;							//存储器0地址
	u32 Mem1Addr;							//存储器1地址
	DMA_FIFO_THRES FIFO_Thres;				//非直接模式下,FIFO阈值容量选择
	u16 TranDataCount;						//传输数据长度-外设到存储器是流控无需设置长度
	bool isDoubleBuffer;					//使能双缓冲模式
	bool isPerIncPsizeAuto;					//外设偏移量自动根据PSIZE设置(TRUE:偏移量与 PSIZE 相关;否则4字节对齐,如果位 PINC =“0”,则此位没有意义)	
	bool isMemInc;							//存储器地址自增
	bool isPerInc;							//外设地址自增
	bool isCircMode;						//循环模式	
	bool isPreFlowCtrl;						//外设是流控制设备
	bool isEnableTranComplInt;				//传输完成中断使能	
	bool isDirectMode;						//直接模式
	bool isEnableStream;					//是否使能数据流-开始传输
}DAM_CONFIG;


//DMA中断定义
#define DAM_INT_FIFO_ERROR		BIT0		//数据流FIFO错误中断
#define DMA_INT_DIRECT_ERROR	BIT2		//直接模式错误中断
#define DMA_INT_TRANS_ERROR		BIT3		//传输错误
#define DMA_INT_TRANS_HALF		BIT4		//传输过半
#define DMA_INT_TRANS_COMPL		BIT5		//传输完成中断
#define DMA_INT_ALL				(0x3D)		//所有中断


void DMA_Config(DMAxSx_CH_TYPE DMAxSx_Ch, DAM_CONFIG *pConfig);									//DMA配置
void DMA_StartTrans(DMAxSx_CH_TYPE DMAxSx_Ch, u32 Mem0Addr, u32 Mem1Addr, u16 TranDataCount);	//启动DMA 传输
void DMA_StopTrans(DMAxSx_CH_TYPE DMAxSx_Ch);													//关闭 DMA 传输
u32 DMA_GetIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch);													//获取DMA中断状态
void DMA_ClearIntStatus(DMAxSx_CH_TYPE DMAxSx_Ch, u32 IntStatus);								//清除DMA中断状态
u8 DMA_GetCurrentTargetBuffIndex(DMAxSx_CH_TYPE DMAxSx_Ch);										//获取双缓冲模式下当前使用的存储器缓冲区索引(0,1)


#endif //__DMA_H_
发布了147 篇原创文章 · 获赞 372 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/104413696