CH32V103应用教程——DMA(存储器到外设)
关于DMA,具有三种数据传输方式:存储器到存储器、存储器到外设、外设到存储器。前面已讲解过关于存储器到存储器数据传输方式,本章将讲解存储器到外设的传输方式以及在下一章将会讲解外设到存储器的传输方式。关于DMA存储器到外设传输方式,程序中,首先定义一个静态的源数据,存放在内部 FLASH中,然后通过DMA的方式传输到串口的数据寄存器,然后通过串口把这些数据发送到电脑的上位机显示出来。
1、DMA简介及相关函数介绍 直接存储器访问控制器(DMA)提供在外设和存储器之间或者存储器和存储器之间的高速数据传输方式,无须CPU干预,数据可以通过DMA快速地移动,以节省CPU的资源来做其他操作。 DMA控制器有7个通道,每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各通道之间的优先级。 DMA作为一种高效、高速的数据传输方式,具有以下几个特性: - 具有7个独立可配置通道,且每个通道都连接专用的硬件DMA请求,并支持软件触发
- 支持循环的缓冲器管理
- 多个通道之间的请求优先权可以通过软件编程设置(最高、高、中和低),优先权设置相等时由通道号决定(通道号低优先级高)
- 支持三种传输方式:存储器到存储器、存储器到外设、外设到存储器
- 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标
- 独立数据源独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
- 每个通道都有3个事件标志(DMA传输过半、DMA传输完成和DMA传输错误),这3个事件标志逻辑或成为一个单独的中断请求
关于DMA具体信息,可参考CH32V103应用手册。DMA标准库函数第十三章已做过介绍,在此不再赘述。
2、硬件设计 本章教程所用资源均为CH32V103开发板内部资源,无需进行其他硬件连接,只需进行程序配置即可。
3、软件设计 本章主要进行存储器到外设的DMA数据传输方式,其相较于存储器到存储器的传输方式,程序中对DMA配置进行一些修改即可,具体如下: dma.h文件 #ifndef __DMA_H
#define __DMA_H
#include "ch32v10x_conf.h"
void DMA1_CH4_Init(void); //DMA传输参数初始化配置
#endif
dma.h文件主要进行函数声明; dma.c文件 #include "dma.h"
u8 SRC_BUF[]= "DMA test: from memory to peripheral";
#define TxSize1 (sizeof(SRC_BUF))
/*******************************************************************************
* Function Name : DMA1_CH4_Init
* Description : Initializes Channel4 of DMA1 collection.
* Input : None
* Return : None
*******************************************************************************/
//DMA1通道4传输参数配置
void DMA1_CH4_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA1时钟
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DATAR); //设置外设地址(外设串口1)
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(SRC_BUF); //设置存储器地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //设置传输方向:存储器到外设
DMA_InitStructure.DMA_BufferSize = TxSize1; //设置传输大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //指定外设地址不变。
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //指定存储器地址递增。
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //设置存储器数据单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置对应DMA工作模式为正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //设置DMA1通道4优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止使能DMA存储器到存储器的传输方式
DMA_Init(DMA1_Channel4, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA1通道4
DMA_ClearFlag(DMA1_FLAG_TC4); //清除DMA1通道4传输完成挂起标志
DMA_Cmd(DMA1_Channel4, ENABLE); //使能DMA1通道4
}
dma.c文件主要进行DMA传输参数初始化配置。DMA存储器到外设传输方式,相较于存储器到存储器传输方式,具体修改如下: DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DATAR);
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(SRC_BUF);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = TxSize1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- 关于DMA存储器地址,与之前一样,设置存储器地址递增:
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- 关于DMA存储器数据单位和外设数据单位,设为一样,与之前一致:
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //设置存储器数据单位
- 关于DMA工作模式以及DMA通道优先级,与之前一致:
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置对应DMA工作模式为正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //设置DMA1通道4优先级
- 关于DMA传输方式及传输方向使能,禁止使能DMA存储器到存储器传输方式:
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
此外,由CH32V103应用手册可知,本次所用外设串口1对应DMA通道4,如下图: 因此,初始化以及使能DMA通道4: DMA_Init(DMA1_Channel4, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA1通道4
DMA_ClearFlag(DMA1_FLAG_TC4); //清除DMA1通道4传输完成挂起标志
DMA_Cmd(DMA1_Channel4, ENABLE); //使能DMA1通道4
4、下载验证 将编译好的程序下载到开发板并复位,可见存储器存储数据被发送到串口:
|