小红书网站开发费用,石家庄网站制作机构,石景山网站建设好的公司,分阶段建设网站目录
一、DMA简介
二、DMA主要特性 三、DMA框图
3.1 DMA处理 3.2 仲裁器 3.3 DMA通道
扩展: 断言#xff1a;
枚举#xff1a; 3.4 可编程的数据传输宽度、对齐方式和数据大小端 3.5 DMA请求映像
四、DMA基本结构
4.1 DMA_Init配置
4.2 实现DMAADC扫描模式
实现要求…目录
一、DMA简介
二、DMA主要特性 三、DMA框图
3.1 DMA处理 3.2 仲裁器 3.3 DMA通道
扩展: 断言
枚举 3.4 可编程的数据传输宽度、对齐方式和数据大小端 3.5 DMA请求映像
四、DMA基本结构
4.1 DMA_Init配置
4.2 实现DMAADC扫描模式
实现要求
存储器映射 ADC_DR寄存器 代码 4.2.1 配置时钟 4.2.2 GPIO初始化 4.2.3 ADC配置ADC连续模式 4.2.4 DMA初始化DMA循环模式 4.2.5 使能与校准 4.2.6 ADC触发
有一定的区别 一、DMA简介 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预数据可以通过DMA快速地移动这就节省了CPU的资源来做其他操作。 两个DMA控制器有12个通道(DMA1有7个通道DMA2有5个通道)每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
二、DMA主要特性 12个独立的可配置的通道(请求)DMA1有7个通道DMA2有5个通道每个通道都直接连接专用的硬件DMA请求每个通道都同样支持软件触发。这些功能通过软件来配置在同一个DMA模块上多个请求间的优先权可以通过软件编程设置(共有四级很高、高、中等和低)优先权设置相等时由硬件决定(请求0优先于请求1依此类推) 独立数据源和目标数据区的传输宽度(字节、半字、全字)模拟打包和拆包的过程源和目标地址必须按数据传输宽度对齐每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错)这3个事件标志逻辑或成为一个单独的中断请求。 三、DMA框图 没有DMA 1.如果没有DMA,CPU传输数据还要以内核作为中转站比如要将ADC采集的数据转移到到SRAM中这个过程是这样的 内核通过DCode经过总线矩阵协调从获取AHB存储的外设ADC采集的数据 然后内核再通过DCode经过总线矩阵协调把数据存放到内存SRAM中。 有DMA的话 DMA传输时外设对DMA控制器发出请求。 DMA控制器收到请求触发DMA工作。 DMA控制器从AHB外设获取ADC采集的数据存储到DMA通道中 DMA控制器的DMA总线与总线矩阵协调使用AHB把外设ADC采集的数据经由DMA通道存放到SRAM中这个数据的传输过程中完全不需要内核的参与也就是不需要CPU的参与。 在发生一个事件后外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时外设立即释放它的请求。一旦外设释放了这个请求DMA控制器同时撤销应答信号。如果有更多的请求时外设可以启动下一个周期。 3.1 DMA处理 每次DMA传送由3个操作组成 ● 从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。 ● 存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。 ● 执行一次DMA_CNDTRx寄存器的递减操作该寄存器包含未完成的操作数目。 DMA通道x外设地址寄存器,DMA_CPARx---外设数据寄存器的基地址作为数据传输的源或目标。DMA通道x存储器地址寄存器,DMA_CMARx---存储器地址存储器地址作为数据传输的源或目标。DMA通道x传输数量寄存器,DMA_CNDTRx---数据传输数量 (Number of data to transfer) 3.2 仲裁器 仲裁器根据通道请求的优先级来启动外设/存储器的访问。 优先权管理分2个阶段 ● 软件每个通道的优先权可以在DMA_CCRx寄存器中设置有4个等级 ─ 最高优先级 ─ 高优先级 ─ 中等优先级 ─ 低优先级 ● 硬件如果2个请求有相同的软件优先级则较低编号的通道比较高编号的通道有较高的优先权。举个例子通道2优先于通道4。 注意 在大容量产品和互联型产品中DMA1控制器拥有高于DMA2控制器的优先级 3.3 DMA通道 每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。DMA传输的数据量是可编程的最大达到65535。包含要传输的数据项数量的寄存器在每次传输后递减。通道配置过程下面是配置DMA通道x的过程(x代表通道号) 1. 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时这个地址将是数据传输的源或目标。 2. 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时传输的数据将从这个地址读出或写入这个地址。 3. 在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后这个数值递减。 4. 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。 5. 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。 循环模式循环模式用于处理循环缓冲区和连续的数据传输(如ADC的扫描模式)。在DMA_CCRx寄存器中的CIRC位用于开启这一功能。当启动了循环模式数据传输的数目变为0时将会自动地被恢复成配置通道时设置的初值DMA操作将会继续进行。
下文详细介绍了两者区别 【精选】STM32 DMA 循环模式DMA_Mode_Circular详解_dma循环模式和正常模式-CSDN博客 DMA通道的操作可以在没有外设请求的情况下进行这种操作就是存储器到存储器模式。 当设置了DMA_CCRx寄存器中的MEM2MEM位之后在软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时DMA传输结束。存储器到存储器模式不能与循环模式同时使用。初始化代码如下所示 /*DMA初始化*/DMA_InitTypeDef DMA_InitStructure; //定义结构体变量DMA_InitStructure.DMA_PeripheralBaseAddr AddrA; //外设基地址给定形参AddrADMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; //外设数据宽度选择字节DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Enable; //外设地址自增选择使能DMA_InitStructure.DMA_MemoryBaseAddr AddrB; //存储器基地址给定形参AddrBDMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //存储器数据宽度选择字节DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; //存储器地址自增选择使能DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; //数据传输方向选择由外设到存储器DMA_InitStructure.DMA_BufferSize Size; //转运的数据大小转运次数DMA_InitStructure.DMA_Mode DMA_Mode_Normal; //模式选择正常模式DMA_InitStructure.DMA_M2M DMA_M2M_Enable; //存储器到存储器选择使能DMA_InitStructure.DMA_Priority DMA_Priority_Medium; //优先级选择中等DMA_Init(DMA1_Channel1, DMA_InitStructure); //将结构体变量交给DMA_Init配置DMA1的通道1 方法1DMA_Mode_Normal正常模式当一次DMA数据传输完后停止DMA传送 也就是只传输一次当通道配置为非循环模式时传输结束后(即传输计数变为0)将不再产生DMA操作。要开始新的DMA传输需要在关闭DMA通道的情况下在DMA_CNDTRx寄存器中重新写入传输数目。配置代码如下
/*** 函 数启动DMA数据转运* 参 数无* 返 回 值无*/
void MyDMA_Transfer(void)
{DMA_Cmd(DMA1_Channel1, DISABLE); //DMA失能在写入传输计数器之前需要DMA暂停工作DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size); //写入传输计数器指定将要转运的次数DMA_Cmd(DMA1_Channel1, ENABLE); //DMA使能开始工作while (DMA_GetFlagStatus(DMA1_FLAG_TC1) RESET); //等待DMA工作完成DMA_ClearFlag(DMA1_FLAG_TC1); //清除工作完成标志位
}
扩展:
DMA_GetFlagStatus函数详解
1. 这一段就是说DMA1还是DMA2空闲。
//注意 #define FLAG_Mask ((uint32_t)0x10000000) //相与同1为1其余为0
DMA1和DMA2这一位有区别,如下这样可以简单的判断执行哪一句。 2. 这一段就是枚举与断言 断言 函数作用 枚举
typedef enum //此处的day可以省略
{saturday,sunday 0,monday,tuesday,wednesday,thursday,friday
} workday; // 此处的 workday 为枚举型 enum day 的别名workday today, tomorrow; // 变量 today 和 tomorrow 的类型为枚举型 workday即 enum day
typedef enum {RESET 0, SET !RESET} FlagStatus, ITStatus; 这句话意思就是给enum {RESET 0, SET !RESET}起了别名FlagStatus和ITStatus 3. 底层源码
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
{FlagStatus bitstatus RESET;uint32_t tmpreg 0;/* Check the parameters */assert_param(IS_DMA_GET_FLAG(DMAy_FLAG));/* Calculate the used DMAy */if ((DMAy_FLAG FLAG_Mask) ! (uint32_t)RESET){/* Get DMA2 ISR register value */tmpreg DMA2-ISR ;}else{/* Get DMA1 ISR register value */tmpreg DMA1-ISR ;}/* Check the status of the specified DMAy flag */if ((tmpreg DMAy_FLAG) ! (uint32_t)RESET){/* DMAy_FLAG is set */bitstatus SET;}else{/* DMAy_FLAG is reset */bitstatus RESET;}/* Return the DMAy_FLAG status */return bitstatus;
} 方法2DMA_Mode_Circular 循环传输模式当传输结束时硬件自动会将传输数据量寄存器进行重装进行下一轮的数据传输。也就是多次传输模式。在循环模式下最后一次传输结束时DMA_CNDTRx寄存器的内容会自动地被重新加载为其初始数值内部的当前外设/存储器地址寄存器也被重新加载为DMA_CPARx/DMA_CMARx寄存器设定的初始基地址。 6. 设置DMA_CCRx寄存器的ENABLE位启动该通道。 一旦启动了DMA通道它既可响应连到该通道上的外设的DMA请求。 一旦启动了DMA通道它既可响应连到该通道上的外设的DMA请求。 当传输一半的数据后半传输标志(HTIF)被置1当设置了允许半传输中断位(HTIE)时将产生一个中断请求。 在数据传输结束后传输完成标志(TCIF)被置1当设置了允许传输完成中断位(TCIE)时将产生一个中断请求。 3.4 可编程的数据传输宽度、对齐方式和数据大小端 每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。DMA传输的数据量是可编程的最大达到65535。包含要传输的数据项数量的寄存器在每次传输后递减。 3.5 DMA请求映像 从外设(TIMx[x1、2、3、4]、ADC1、SPI1、SPI/I2S2、I2Cx[x1、2]和USARTx[x1、2、3])产生的7个请求通过逻辑或输入到DMA1控制器这意味着同时只能有一个请求有效。参见下图的DMA1请求映像。 外设的DMA请求可以通过设置相应外设寄存器中的控制位被独立地开启或关闭。 四、DMA基本结构 4.1 DMA_Init配置
#include stm32f10x.h // Device headeruint16_t MyDMA_Size; //定义全局变量用于记住Init函数的Size供Transfer函数使用/*** 函 数DMA初始化* 参 数AddrA 原数组的首地址* 参 数AddrB 目的数组的首地址* 参 数Size 转运的数据大小转运次数* 返 回 值无*/
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{MyDMA_Size Size; //将Size写入到全局变量记住参数Size/*开启时钟*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA的时钟/*DMA初始化*/DMA_InitTypeDef DMA_InitStructure; //定义结构体变量DMA_InitStructure.DMA_PeripheralBaseAddr AddrA; //外设基地址给定形参AddrADMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; //外设数据宽度选择字节DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Enable; //外设地址自增选择使能DMA_InitStructure.DMA_MemoryBaseAddr AddrB; //存储器基地址给定形参AddrBDMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; //存储器数据宽度选择字节DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; //存储器地址自增选择使能DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; //数据传输方向选择由外设到存储器DMA_InitStructure.DMA_BufferSize Size; //转运的数据大小转运次数DMA_InitStructure.DMA_Mode DMA_Mode_Normal; //模式选择正常模式DMA_InitStructure.DMA_M2M DMA_M2M_Enable; //存储器到存储器选择使能DMA_InitStructure.DMA_Priority DMA_Priority_Medium; //优先级选择中等DMA_Init(DMA1_Channel1, DMA_InitStructure); //将结构体变量交给DMA_Init配置DMA1的通道1/*DMA使能*/DMA_Cmd(DMA1_Channel1, DISABLE); //这里先不给使能初始化后不会立刻工作等后续调用Transfer后再开始
}/*** 函 数启动DMA数据转运* 参 数无* 返 回 值无*/
void MyDMA_Transfer(void)
{DMA_Cmd(DMA1_Channel1, DISABLE); //DMA失能在写入传输计数器之前需要DMA暂停工作DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size); //写入传输计数器指定将要转运的次数DMA_Cmd(DMA1_Channel1, ENABLE); //DMA使能开始工作while (DMA_GetFlagStatus(DMA1_FLAG_TC1) RESET); //等待DMA工作完成DMA_ClearFlag(DMA1_FLAG_TC1); //清除工作完成标志位
}4.2 实现DMAADC扫描模式
实现要求 存储器映射 类型 起始地址 存储器 用途 ROM 0x0800 0000 程序存储器Flash 存储C语言编译后的程序代码,常量数据 0x1FFF F000 系统存储器 存储BootLoader用于串口下载 0x1FFF F800 选项字节 存储一些独立于程序代码的配置参数 RAM 0x2000 0000 运行内存SRAM 存储运行过程中的临时变量 0x4000 0000 外设寄存器 存储各个外设的配置参数 0xE000 0000 内核外设寄存器 存储内核各个外设的配置参数NVIC、systick ADC将菜做好了DMA负责将菜及时的交给顾客厨师与服务员的关系那服务员从哪里端菜了查数据手册第一句话就是在规则组下一次只能上一个菜需要使用服务员及时的端菜。第二句话就是告诉我们服务员端菜的地方在ADC_DR寄存器。 那么菜最终端给的顾客是谁根据程序要求我们这里的顾客是SRAM。 ADC_DR寄存器
#define ADC1 ((ADC_TypeDef *) ADC1_BASE)
#define ADC1_BASE (APB2PERIPH_BASE 0x2400) #define ADC_DR_DATA ((uint32_t)0x0000FFFF) /*! Regular data */
#define ADC_DR_ADC2DATA ((uint32_t)0xFFFF0000) /*! ADC2 data */ 代码 4.2.1 配置时钟 DMA1\ADC1\GPIOA
/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1的时钟/*设置ADC时钟*/RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频ADCCLK 72MHz / 6 12MHz 4.2.2 GPIO初始化
/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure); //将PA0、PA1、PA2和PA3引脚初始化为模拟输入 4.2.3 ADC配置ADC连续模式 ADC_InitStructure.ADC_ContinuousConvMode ENABLE; //连续转换使能每转换一次规则组序列后立刻开始下一次转换
/*规则组通道配置*/ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置配置为通道0ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); //规则组序列2的位置配置为通道1ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); //规则组序列3的位置配置为通道2ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); //规则组序列4的位置配置为通道3/*ADC初始化*/ADC_InitTypeDef ADC_InitStructure; //定义结构体变量ADC_InitStructure.ADC_Mode ADC_Mode_Independent; //模式选择独立模式即单独使用ADC1ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; //数据对齐选择右对齐ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; //外部触发使用软件触发不需要外部触发ADC_InitStructure.ADC_ContinuousConvMode ENABLE; //连续转换使能每转换一次规则组序列后立刻开始下一次转换ADC_InitStructure.ADC_ScanConvMode ENABLE; //扫描模式使能扫描规则组的序列扫描数量由ADC_NbrOfChannel确定ADC_InitStructure.ADC_NbrOfChannel 4; //通道数为4扫描规则组的前4个通道ADC_Init(ADC1, ADC_InitStructure); //将结构体变量交给ADC_Init配置ADC1 4.2.4 DMA初始化DMA循环模式 循环模式用于处理循环缓冲区和连续的数据传输(如ADC的扫描模式)。 DMA_InitStructure.DMA_Mode DMA_Mode_Circular; //模式选择循环模式与ADC的连续转换一致这样ADC每次上菜DMA马上拿走一直循环 /*DMA初始化*/DMA_InitTypeDef DMA_InitStructure;定义结构体变量DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; 外设基地址给定形参AddrADMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord;
外设数据宽度选择半字对应16为的ADC数据寄存器DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; 外设地址自增选择失能始终以ADC数据寄存器为源DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)AD_Value; 存储器基地址给定存放AD转换结果的全局数组AD_ValueDMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; 存储器数据宽度选择半字与源数据宽度对应DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; 存储器地址自增选择使能每次转运后数组移到下一个位置DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; 数据传输方向选择由外设到存储器ADC数据寄存器转到数组DMA_InitStructure.DMA_BufferSize 4; 转运的数据大小转运次数与ADC通道数一致DMA_InitStructure.DMA_Mode DMA_Mode_Circular; 模式选择循环模式与ADC的连续转换一致DMA_InitStructure.DMA_M2M DMA_M2M_Disable; 存储器到存储器选择失能数据由ADC外设触发转运到存储器DMA_InitStructure.DMA_Priority DMA_Priority_Medium; 优先级选择中等DMA_Init(DMA1_Channel1, DMA_InitStructure); 将结构体变量交给DMA_Init配置DMA1的通道1 注意 DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; //外设基地址给定形参AddrA如果不进行强制类型转换会报错-----类型为“volatile uint32_t *”的值不能赋值给类型为“uint32_t”的实体。 #define MAXTIME 1000,一个简单的MAXTIME就定义好了它代表1000如果在程序里面写
if(iMAXTIME){.........},编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。 #define ADC1 ((ADC_TypeDef *) ADC1_BASE)一个ADC_TypeDef结构体指针类型的变量ADC1_BASE。 // 访问数据操作如下 data.age 24; // 结构体变量通过点运算符( . )访问 pdata-age 24; // 指向结构体的指针通过箭头运算符( - )访问
typedef struct // 定义一个结构体类型DATA
{char key[10]; // 结构体成员keychar name[20]; // 结构体成员nameint age; // 结构体成员age
}DATA;DATA data; // 声明一个结构体变量
DATA *pdata; // 声明一个指向结构体的指针// 访问数据操作如下
data.age 24; // 结构体变量通过点运算符( . )访问
pdata-age 24; // 指向结构体的指针通过箭头运算符( - )访问
结构体指针的访问变量方法 1p-结构体成员 2(*p).结构体成员
p-num 的含义是指针变量 p 所指向的结构体变量中的 num 成员。p-num 最终代表的就是 num 这个成员中的内容。 4.2.5 使能与校准 因为 DMA_InitStructure.DMA_M2M DMA_M2M_Disable; // 存储器到存储器选择失能数据由ADC外设触发转运到存储器硬件触发 由于DMA转运有三个条件开关控制DMA_CMD必须使能传输计数器必须大于0当寄存器的内容为0时无论通道是否开启都不会发生任何数据传输。触发源必须有触发信号。 前文提到对于DMA正常模式当一次DMA数据传输完后停止DMA传送 也就是只传输一次当通道配置为非循环模式时传输结束后(即传输计数变为0)将不再产生DMA操作。且ADC单次转换下ADC只执行一次转换。相当于没有开启ADC到DMA的通道
所以这里需要开启ADC到DMA的输出用到下图函数 /*DMA和ADC使能*/DMA_Cmd(DMA1_Channel1, ENABLE); //DMA1的通道1使能ADC_DMACmd(ADC1, ENABLE); //ADC1触发DMA1的信号使能ADC_Cmd(ADC1, ENABLE); //ADC1使能/*ADC校准*/ADC_ResetCalibration(ADC1); //固定流程内部有电路会自动执行校准while (ADC_GetResetCalibrationStatus(ADC1) SET);ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1) SET); 4.2.6 ADC触发
/*ADC触发*/ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发ADC开始工作由于ADC处于连续转换模式故触发一次后ADC就可以一直连续不断地工作
当不是ADC连续模式的时候DMA也不是循环模式时
有一定的区别 加上下代码即可最大的区别就是需要不断的开启 ADC ADC_SoftwareStartConvCmd(ADC1,ENABLE); 上文连续模式下由于ADC处于连续转换模式故触发一次后ADC就可以一直连续不断地工作。 1. 告诉DMA我做了ADC做了4个菜2.ADC开始做菜3.DMA取菜一个个拿DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag.
void AD_GetValue(void)
{DMA_Cmd(DMA1_Channel1,DISABLE);DMA_SetCurrDataCounter(DMA1_Channel1,4);DMA_Cmd(DMA1_Channel1,ENABLE);ADC_SoftwareStartConvCmd(ADC1,ENABLE);while(DMA_GetFlagStatus(DMA1_FLAG_TC1) RESET);DMA_ClearFlag(DMA1_FLAG_TC1);
}