打印

百为STM32开发板教程之十五——DMA

[复制链接]
1425|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xi_liang|  楼主 | 2013-10-19 09:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
百为STM32开发板教程之十五——DMA

实验目的:
使用DMA1的通道6,把存放在FLASH里面的一段数据用DMA传输到RAM里面。
传送完成后把数据打印到串口上。

STM32两个DMA控制器共有12个独立可配置的通道,其中DMA1有7个通道,DMA2有5个通道。
主要特性有:
1、12个独立的可配置的通道(请求):DMA1有7个通道,DMA2有5个通道
2、独立的源数据和目的数据传输宽度(字节、半字、全字),源数据和目的数据地址必须按数据传输宽度对齐。
3、每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错)
4、同一个DMA控制器上,多个DMA请求有优先级之分,共有四级:很高、高、中等和低。
5、支持存储器和存储器间的传输
6、外设和存储器、存储器和外设之间的传输

DMA的功能:
直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。

DMA功能框图,如下图所示:
2013-9-10 01:30 上传
下载附件 (112.18 KB)




每次DMA的传输包括三个步骤:
1、从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
2、存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
3、执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

DMA1各通道请求分配:
2013-9-10 01:50 上传
下载附件 (138.96 KB)



从外设(TIMx[x=1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x=1、2]和USARTx[x=1、2、3])产生的7个请求,通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。

DMA2各通道请求分配:
2013-9-10 01:50 上传
下载附件 (110.48 KB)



从外设(TIMx[5、6、7、8]、ADC3、SPI/I2S3、UART4、DAC通道1、2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,这意味着同时只能有一个请求有效。

DMA通道配置过程:
下面是配置DMA通道x的过程(x代表通道号):
1、在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将是数据传输的源或目标。
2、在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数据将从这个地址读出或写入这个地址。
3、在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
4、在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。
5、在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。
6、设置DMA_CCRx寄存器的ENABLE位,启动该通道。
一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。 当传输一半的数据后,半传输标志(HTIF)被置1,当设置了允许半传输中断位(HTIE)时,将产生一个中断请求。在数据传输结束后,传输完成标志(TCIF)被置1,当设置了允许传输完成中断位(TCIE)时,将产生一个中断请求。

  /* 配置DMA1 通道6 */
  DMA_DeInit(DMA1_Channel6);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;  //设置外设地址,把这个地址作为传送的数据源地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)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的循环模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;  //设置DMA通道的优先级
  DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; //设置存储器到存储器模式
  DMA_Init(DMA1_Channel6, &DMA_InitStructure);  //把上面的配置(DMA_InitStructure)通过DMA_Init函数写入到相应的寄存器

  /* 使能DMA1通道6传输完成中断 */
  DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);

  /* 获得传送之前当前数据计数值 */
  CurrDataCounterBegin = DMA_GetCurrDataCounter(DMA1_Channel6);

  /* 使能DMA1通道6传输 */
  DMA_Cmd(DMA1_Channel6, ENABLE);

  /* 等待传输完成 */
  while (CurrDataCounterEnd != 0)
  {
  }
printf("Transfer complete.\n\r");

  /* 打印源数据内容 */
for(count = 0; count < BufferSize; count++)
{
  printf("0x%x ", SRC_Const_Buffer[count]);
}

  /* 打印目的数据内容 */
for(count = 0; count < BufferSize; count++)
{
  printf("0x%x ", DST_Buffer[count]);
}
沙发
90chinazhu| | 2014-4-12 21:33 | 只看该作者
mark

使用特权

评论回复
板凳
xi_liang|  楼主 | 2014-5-15 23:36 | 只看该作者
这个看来用得人少,顶起

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:http://baiweijishu.taobao.com/ 百为STM32开发板 兼容官方STM3210E-EVAL开发板 WM-G-MR-09 WIFI开发板

41

主题

285

帖子

10

粉丝