STM32-(35):DMA传输控制(实验)

上一篇:STM32-(34):DMA传输控制(理论) 下一篇:STM32-(36):CAN总线(概述)

实验内容:

通过DMA 进行数据传输,实现两块内存空间的拷贝,如果两块内存中的数据一致,蜂鸣器会响起,否则不响。

代码

/***********************************************************************
* 文件 : main.c
* 说明 :存储器与存储器之间的DMA传输
* 说明 :通过DMA进行数据传输,实现两块内存空间的拷贝,如果两块内存中的数据一致,蜂鸣器会响起,否则不响
************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"	  //包含了所有的头文件 它是唯一一个用户需要包括在自己应用中的文件,起到应用和库之间界面的作用。
#include 

typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;	  //定义一个枚举

#define BufferSize	32	 //定义缓存区大小

vu16 CurrDataCounter_Begin = 0;	//DMA传输开始时的数据的大小
vu16 CurrDataCounter_End = 0;	//DMA传输结束后数据的大小
TestStatus TransferStatus;	//发送状态 ,用来表示数据传输是否正确完成,如果传输成功为1,否则为0;
//ErrorStatus	HSEStartUpStatus;  

uc32 SRC_Const_Buffer[BufferSize] = {0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,  //源数据的地址
                                     0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                                     0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
                                     0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
                                     0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
                                     0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
                                     0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
                                     0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};

u32 DST_Buffer[BufferSize];	  //目的数组:用来保存源地址中的数据

void Delay_Ms(u16 time);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void DMA1_Channel6_Configuration(void);
TestStatus Buffercmp(uc32 *pBuffer,u32* pBuffer1,u16 BufferLength);	 //比较两内存块中的数据是否相等


/* Private functions ---------------------------------------------------------*/ 
/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
	#ifdef DEBUG
  	debug();
	#endif
	u8 i;
  	RCC_Configuration();    //使能外设时钟
  	GPIO_Configuration();   //初始化GPIO管脚
	GPIO_SetBits(GPIOA, GPIO_Pin_3); //关闭蜂鸣器
	NVIC_Configuration();
	DMA1_Channel6_Configuration(); //DMA通道6的配置

	//--------------
	TransferStatus = Buffercmp(SRC_Const_Buffer, DST_Buffer, BufferSize);
			

  	while (1)
	{
		if(TransferStatus == 1)	 //如果两块内存空间的数据一样
		{
			for(i=0;i<5;i++)
			{
				GPIO_SetBits(GPIOA, GPIO_Pin_3);
				Delay_Ms(1000);
				GPIO_ResetBits(GPIOA, GPIO_Pin_3);
				Delay_Ms(1000);
				GPIO_SetBits(GPIOA, GPIO_Pin_3);
				Delay_Ms(1000);	
			}	
		}
	}
}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : time (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_Ms(u16 time)  //延时函数
{ 
	u16 i,j;
	for(i=0;i0;j--);
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void) 
{
	//=============================== 使用内部RC晶振 ===================================
    /*   
	RCC_HSICmd(ENABLE);//使能内部高速晶振 ;
 	RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//选择内部高速时钟作为系统时钟SYSCLOCK=8MHZ	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);//选择HCLK时钟源为系统时钟SYYSCLOCK
  	RCC_PCLK1Config(RCC_HCLK_Div4);//APB1时钟为2M 
  	RCC_PCLK2Config(RCC_HCLK_Div4);//APB2时钟为2M
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);//使能APB2外设GPIOB时钟
	*/

	//==========================使用外部RC晶振========================================
  	RCC_DeInit();				//初始化为缺省状态
  	RCC_HSEConfig(RCC_HSE_ON);  //高速时钟使能
  	while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  //等待高速时钟使能就绪

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer 
    FLASH_SetLatency(FLASH_Latency_2);	  					// Flash 2 wait state 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 						// HCLK = SYSCLK 
    RCC_PCLK2Config(RCC_HCLK_Div1);							// PCLK2 = HCLK 
    RCC_PCLK1Config(RCC_HCLK_Div2);	  						// PCLK1 = HCLK/2 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);	// PLLCLK = 8MHz * 9 = 72 MHz  
    RCC_PLLCmd(ENABLE);	  									// Enable PLL 
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);		// Wait till PLL is ready 

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	  			// Select PLL as system clock source 
    while(RCC_GetSYSCLKSource() != 0x08);					// Wait till PLL is used as system clock source 

	//==============================使能相应的外设时钟=========================================
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
 	
	
	#ifdef  VECT_TAB_RAM  
	  	NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
	#else
	  	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
	#endif

	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQChannel;	  //DMA中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);

}
/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : 初始化GPIO外设
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;		//声明一个结构体变量
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 	//选择PA.3
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 //管脚频率为50MHZ
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	 //输出模式为推挽输出
	GPIO_Init(GPIOA,&GPIO_InitStructure);				 //初始化GPIOA寄存器		
}

void DMA1_Channel6_Configuration(void)
{
	DMA_InitTypeDef	DMA_InitStructure;
	DMA_DeInit(DMA1_Channel6);	// 将DMA1_Channel6寄存器重设为初始值 ;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_Const_Buffer; 	//用来定义DMA外设的基地址(源地址)
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DST_Buffer;				//用来定义DMA内存的基地址(目的地址)
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;					//传输方向
	DMA_InitStructure.DMA_BufferSize = BufferSize;						//传输数据的大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;		//DMA外设地址+1
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;				//DMA内存地址+1
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//传输的字节宽度(数据宽度为32 位)
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;		   //接受的字节宽度(数据宽度为32 位)
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;						   //传输模式(正常模式就是非循环模式,内存到内存也只能设为正常模式)
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;					   //优先级(设置为最高优先级)
	DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;							   //使能内存到内存的传输(允许开启)
	DMA_Init(DMA1_Channel6,&DMA_InitStructure);							  //初始化(至此DMA设置完成)

	//中断配置(对通道6进行配置,第二个参数为 传输完成中断屏蔽,传输完成之后就会产生一个中断信号)
	DMA_ITConfig(DMA1_Channel6,DMA_IT_TC,ENABLE);						 

	CurrDataCounter_End = DMA_GetCurrDataCounter(DMA1_Channel6); //返回通道6内带传输数据的数目

	DMA_Cmd(DMA1_Channel6,ENABLE);	   					//使能DMA
}
/**********************************************************************
* 函数名称:TestStatus Buffercmp(uc32* pBuffer,u32* pBuffer1,u16 BufferLength)	 //比较数据是否相同
* 函数功能:用来测试两块内存中的数据是否一致
* 入口参数:
				uc32* pBuffer:				源数据的地址指针
				u32* pBuffer:				目的数据的地址指针
				u16 BufferLength:			比较两块内存数据的个数										
* 出口参数:如果数据相等返回PASSED(1),OR 返回FAILED(0)
**********************************************************************/
TestStatus Buffercmp(uc32* pBuffer,u32* pBuffer1,u16 BufferLength)	 //比较数据是否相同
{
	while(CurrDataCounter_End!=0)  ;
	while(BufferLength--)
	{
		if(*pBuffer != *pBuffer1)	//只要有一个数据不同,返回FAILED,DMA传输出错;
		{
			return FAILED;
		}
		pBuffer++;
		pBuffer1++;
	}
	return	PASSED;
}
上一篇:STM32-(34):DMA传输控制(理论) 下一篇:STM32-(36):CAN总线(概述)

你可能感兴趣的:(STM32-(35):DMA传输控制(实验))