main.c
/*********************************************************
** FileName: DMA传输速度比较
** Description:
分别使用CPU和DMA传输数据,对其计时,使用串口返回时间,对时间进行比较。
** Author: 老猫
** Date: 2019/10/7
** Others:
*********************************************************/
#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "stdio.h"
#include "string.h"
#define BufferSize 32
vu16 CurrDataCounter=0;
vu32 Tick=0;
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 RCC_Configuration(void);
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void DMA_Configuration(void);
void Systick_Configuration(void);
int main (void){//主程序
u8 i=0;
u8 TickCntCPU=0;
u8 TickCntDMA=0;
RCC_Configuration(); //时钟设置
NVIC_Configuration();
GPIO_Configuration();
USART_Configuration();
DMA_Configuration();
Systick_Configuration();
//使用CPU搬运并计时
Tick=0;
for(i=0;i<BufferSize;i++)
{
DST_Buffer[i]=SRC_Const_Buffer[i];
}
TickCntCPU=Tick;
for(i=0;i<BufferSize;i++)
{
DST_Buffer[i]=0;
}
//使用DMA搬运并计时
Tick=0;
DMA_Cmd(DMA1_Channel6,ENABLE);
while(CurrDataCounter!=0);
TickCntDMA=Tick;
//实验结果
if(strncmp((const char *)SRC_Const_Buffer,(const char *)DST_Buffer,BufferSize)==0)
{
printf("\r\nTransmit Success!\r\n");
}
else
{
printf("\r\nTransmit Fault!\r\n");
}
printf("\r\nThe CPU transfer, time consume: %dus!\n\r", TickCntCPU);
printf("\r\nThe DMA transfer, time consume: %dus!\n\r", TickCntDMA);
while(1);
}
void GPIO_Configuration(void)
{
/* 定义 GPIO 初始化结构体 GPIO_InitStructure */
GPIO_InitTypeDef GPIO_InitStructure;
/* 设置 USART1 的Tx脚(PA.9)为第二功能推挽输出功能 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA , &GPIO_InitStructure);
/* 设置 USART1 的Rx脚(PA.10)为浮空输入脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA , &GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
/* 定义NVIC初始化结构体 NVIC_InitStructure */
NVIC_InitTypeDef NVIC_InitStructure;
/* #ifdef...#else...#endif结构的作用是根据预编译条件决定中断向量表起始地址*/
#ifdef VECT_TAB_RAM
/*中断向量表起始地址从 0x20000000 开始*/
NVIC_SetVectorTable(NVIC_VectTab_RAM , 0x0);
#else /* VECT_TAB_FLASH */
/* 中断向量表起始地址从 0x80000000 开始 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH , 0x0);
#endif
/* 选择优先级分组0 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* 开启DMA16通道中断控制,0级先占优先级,0级次占优先级*/
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_Const_Buffer;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DST_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
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_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
CurrDataCounter= DMA_GetCurrDataCounter(DMA1_Channel6);
}
void Systick_Configuration(void)
{
/* 主频为72MHz,配置计数值除以1000可以得到1us定时间隔 */
SysTick_Config(SystemCoreClock / 1000000);
}
void USART_Configuration(void)
{
/* 定义 USART 初始化结构体 USART_InitStructure */
USART_InitTypeDef USART_InitStructure;
/*
* 波特率为115200bps;
* 8位数据长度;
* 1个停止位,无校验;
* 禁用硬件流控制;
* 禁止USART时钟;
* 时钟极性低;
* 在第2个边沿捕获数据
* 最后一位数据的时钟脉冲不从 SCLK 输出;
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1 , &USART_InitStructure);
/* 使能 USART1 */
USART_Cmd(USART1 , ENABLE);
}
/******************************************************************************
* 函数名 : fputc
* 函数描述 : 将printf函数重定位到USATR1
* 输入参数 : 无
* 输出结果 : 无
* 返回值 : 无
******************************************************************************/
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (u8) ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
在SYS.C中
开启DMA USART1 和GPIOA时钟
stm32f10x_it.c
#include "stm32f10x_it.h"
extern vu16 CurrDataCounter;
extern vu32 Tick;
void SysTick_Handler(void)
{
Tick++;
}
void DMA1_Channel6_IRQHandler(void)
{
CurrDataCounter= DMA_GetCurrDataCounter(DMA1_Channel6);
DMA_ClearITPendingBit(DMA1_IT_GL6);
}
结果