上一篇: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总线(概述)