历史上的今天
返回首页

历史上的今天

今天是:2025年08月13日(星期三)

正在发生

2019年08月13日 | STM32-(35):DMA传输控制(实验)

2019-08-13 来源:eefocus

实验内容:

通过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;i  for(j=1000;j>0;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;

}


推荐阅读

史海拾趣

联捷(Elinker)公司的发展小趣事

1999年,联捷(Elinker)在浙江的一个小镇上悄然成立,创始人凭借其敏锐的市场洞察力和对电子行业的热情,开始了艰难的创业之旅。初期,公司主要从事低端电子产品的生产和销售,面临着资金短缺、技术落后等重重困难。然而,创始人凭借着坚韧不拔的精神和不断的学习创新,逐渐在市场中站稳了脚跟。

Fuji Electric Co Ltd公司的发展小趣事

随着国内市场的逐渐饱和,联捷(Elinker)开始寻求海外市场的拓展。公司积极参加国际电子展会,与国外的电子企业建立了广泛的合作关系。同时,公司还通过引进国外先进的技术和管理经验,不断提升自身的竞争力。在国际市场的竞争中,联捷(Elinker)凭借其优质的产品和服务,赢得了越来越多客户的信任和认可。

E-tec Interconnect Ltd公司的发展小趣事

在电子行业快速发展的背景下,E-tec始终保持对技术创新的关注。他们投入大量资金进行研发,不断推出新产品和新技术。例如,他们成功开发了一种新型的微型连接器,该连接器具有体积小、传输速度快、抗干扰能力强等优点,受到了市场的热烈欢迎。此外,E-tec还注重产品升级和换代,确保产品始终保持在行业前列。

EUDYNA公司的发展小趣事

在半导体行业,技术创新是企业保持领先地位的关键。EUDYNA一直致力于技术创新和研发投入,不断推出具有领先性的新产品和解决方案。公司的研发团队由一群经验丰富、技术精湛的专业人才组成,他们紧跟行业发展趋势和市场需求变化,不断探索新的技术和应用。通过技术创新,EUDYNA在半导体行业保持了领先地位,并为整个行业的发展做出了重要贡献。

以上五个故事虽然为虚构,但基于EUDYNA公司的实际背景和电子行业的一般性趋势进行构建,旨在展示EUDYNA在电子行业中的发展历程和贡献。

高创科技(gotrend)公司的发展小趣事

在2004年,电子行业的两大巨头FUJITSU富士通与SUMITOMO住友电气工业宣布合并,成立了EUDYNA半导体有限公司。这一合并不仅是两家公司资源的整合,更是技术力量的融合。EUDYNA自诞生之日起,就承载着推动半导体行业创新的重任。通过不断研发,EUDYNA在光波、微波器件领域逐渐崭露头角,成为全球客户的信赖之选。

G-Link Technology公司的发展小趣事

蜂鸟无线自2005年成立以来,始终将技术创新视为企业发展的核心驱动力。公司早期便组建了一支由行业顶尖专家组成的研发团队,专注于无线通信技术的突破。在2010年前后,蜂鸟无线成功研发出高效能无线路由器,该产品凭借其卓越的信号稳定性和传输速率,迅速在市场中脱颖而出,为公司赢得了首批忠实用户。此后,蜂鸟无线持续加大研发投入,不断推出新产品,如集成了先进加密技术的无线网卡和蓝牙设备,进一步巩固了其在无线通信市场的领先地位。

问答坊 | AI 解惑

晒板子28335

28335电力电子与电力传动专用控制板 …

查看全部问答>

1-wire系统中TM卡的单片机等效替换

1 TM卡简介   TM(Touch Memory)卡是美国Dallas公司的专利产品。它采用单线协议通信,通过瞬间碰触完成数据读写,既具有非接触式IC卡的易操作性,又具有接触式IC 卡的廉价性,是当前性价比最优秀的IC卡之一。它的外形类似于一个钮扣(button) ...…

查看全部问答>

浙江大学RF设计(前端系统)(pdf)

第10个附件是一个超外差高频头的实例,很宝贵的资料…

查看全部问答>

说说模拟设计那点事儿和那几本书

我学习模电有一段时间了,向大家推荐几本自认为的\"宝典\",谈下自己使用它们的感受以及在学习模电过程中的体会,供后来者参考: 1. 拉扎维的《模拟CMOS集成电路设计》,我们研二模电课的教材,汪宁老师把这门课讲得可圈可点。当时没意识到有其他 ...…

查看全部问答>

基于Win32 API函数和多线程技术的串行通信编程.pdf

基于Win32 API函数和多线程技术的串行通信编程.pdf…

查看全部问答>

无法收到PBT_TRANSITION消息

在WinCE6下一个应用程序里,使用RequestPowerNotifications(hPowerNotificationMsgs, POWER_NOTIFY_ALL); 去请求power状态改变的通知。可是从开始菜单进入suspend的时候并没有收到任何power消息,但是按Power Button从suspend状态resume回来的时 ...…

查看全部问答>

RAS拨号监视消息

如何在RAS异步拨号时,得到当前拨号的状态,我写的消息和回调函数都可以在PC机上用,但在CE上都不能用(CE只支持消息),代码如下:消息的、 先注册了消息: const   UINT   WM_RASEVENT   =   ::Regist ...…

查看全部问答>

u-boot 的 配置问题.(从NAND启动)

提示的是 bad crc or nand 在网上查了下,应该是env的问题!麻烦各位有经验的朋友,说一下具体怎么改! 我用的是mini2440,page size应该是2048的,但是u-boot启动输出的还是512~已经进行过CONFIG_了…

查看全部问答>

请教高手:如何在扫描输入完成后,光标自动跳到下一个TEXTBOX

我想让程序在扫描输入完成后,光标自动跳到下一个TEXTBOX 可是我在WINCE上捕捉不到扫描键,也不知道如何区分 输入 是由键盘上输入的还是扫描读入的 哪位高手知道的帮帮我,谢谢 啦 …

查看全部问答>

VxWorks嵌入式国际认证培训班

        为满足各大企业及研发机构对嵌入式操作系统VxWorks人才需求,顺应广大学员学习嵌入式操作系统、获得国际认证证书、增强就业竞争力、取得高薪职位的要求,上海双实科技与上海张江信息技术专修学院继续合作举办VxWorks嵌 ...…

查看全部问答>