历史上的今天
今天是:2025年01月25日(星期六)
2021年01月25日 | ADC,DMA,多路,单次/连续转换
2021-01-25 来源:eefocus

今天回答一个朋友的问题吧,ADC如何使用DMA采集多通道模拟电压。
1写在前面
这个问题其实之前写过一些相关文章,原理我之前也有相关描述。如果想要彻底弄明白其原理,建议阅读《参考手册》、结合标准外设库来理解。
现在很多人习惯使用STM32CubeMX来直接生成初始化代码,如果没有掌握STM32CubeMX、HAL库,使用STM32CubeMX生成的代码,或许就不能满足你的应用。
同时,STM32CubeMX生成的代码,想要根据代码进一步了解其原理,其实很难
ADC转换一些基础原理,我这里就不过多描述了,请直接看下面标准外设库源码、及后面给的注释。
下面写2点:ADC软件单次触发转换,和连续转换。
2ADC,DMA,单次触发转换
这里以ADC,使用DMA,通过软件单次触发转换为例。主要需注意几个相关参数即可。
1.GPIO配置

2.DMA配置

3.ADC配置

4.ADC单次触发转换

5.源代码
/* 静态变量 ------------------------------------------------------------------*/
static volatile uint16_t sADC_Buf[3];
/************************************************
函数名称 : ADC_GPIO_Configuration
功 能 : ADC引脚配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/************************************************
函数名称 : ADC_DMA_Configuration
功 能 : ADC DMA配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* 使能时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* 配置DMA */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));//外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&sADC_Buf[0]); //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //传输方向:外设 -> 内存
DMA_InitStructure.DMA_BufferSize = 3; //传输长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设递增:关闭
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存递增:打开
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
}
/************************************************
函数名称 : ADC_Configuration
功 能 : ADC参数配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
/* 使能时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* ADC配置 */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //浏览模式(多通道)
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转化模式
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = 3; //转换通道数
ADC_Init(ADC1, &ADC_InitStructure);
/* 通道配置 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_3Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE); //使能ADC的DMA功能
ADC_Cmd(ADC1, ENABLE); //使能ADC
}
/************************************************
函数名称 : ADC_Initializes
功 能 : ADC初始化
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_Initializes(void)
{
ADC_GPIO_Configuration();
ADC_DMA_Configuration();
ADC_Configuration();
}
/************************************************
函数名称 : ADC_Get
功 能 : 转换
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_Get(void)
{
DMA_Cmd(DMA2_Stream0, DISABLE); //关闭DMA
//内存地址
DMA_MemoryTargetConfig(DMA2_Stream0, (uint32_t)sADC_Buf, DMA_Memory_0);
DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0); //清除标志位
DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA
ADC_SoftwareStartConv(ADC1); //启动转换
while(RESET == DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0)); //等待转换完成
//得到3条通道转换结果:sADC_Buf
//进行相关换算,处理...
}
提示:以上源代码只为方便学习和理解,请结合实际应用修改、或增减代码。
3ADC,DMA,连续转换
我这里写的连续,是ADC连续转换,同时,DMA循环存储。大部分配置和上面差不多,这种方式也用的比较多,写给大家。
1.DMA配置

2.ADC配置

3.源代码
/* 静态变量 ------------------------------------------------------------------*/
static volatile uint16_t sADC_Buf[3];
/************************************************
函数名称 : ADC_GPIO_Configuration
功 能 : ADC引脚配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/************************************************
函数名称 : ADC_DMA_Configuration
功 能 : ADC DMA配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* 使能时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* 配置DMA */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));//外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&sADC_Buf[0]); //内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //传输方向:外设 -> 内存
DMA_InitStructure.DMA_BufferSize = 3; //传输长度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设递增:关闭
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存递增:打开
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
}
/************************************************
函数名称 : ADC_Configuration
功 能 : ADC参数配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
史海拾趣
|
3G时代,能否替代原有的固定宽带 2009年元月,中国3张3G牌照发放 电信 cdma2000 推出天翼品牌,声称测试速度已经达到3.3Mbps,年底升级到9Mbps。 联通 WCDMA 声称速度达到7.2Mbps,号称最成熟的3G制式。 ...… 查看全部问答> |
|
我有个兄弟,三十一二了,突然问我他可以学编程搞编程吗?他没读过大学,没有任何基础,但他想拥有改变,不知道现不现实! 我有个兄弟,三十一二了,突然问我他可以学编程搞编程吗?他没读过大学,没有任何基础,但他想拥有改变,不知道现不现实! 他的担心有以下几点: 1。没有学历,就算把编程学好了,公司不一定给机会给他 2。岁数不小了,学编程能够学到怎样的程度 ...… 查看全部问答> |
|
想通过单片机里存的根据钢琴简谱的数组(又两部分组成:音符(1,2,3,4,5,6,7)和音长)输出曲子,想问一下有没有这样的芯片或是模块什么的,可以根据单片机7个io口(相当于音符1,2,3,4,5,6,7)输出的脉冲控制其发声(发1,2,3,4,5, ...… 查看全部问答> |
|
本程序主要实现了通过按键选择电机的正转或反转,选择完后,通过up键,加快电机的转速(增大占空比),down键来降低电机的转速。本例程的扩展部分:将按键用外接的电位器来控制,类似于汽车转动方向盘,电机就转到,转动角度越大,转动的速度就越大 ...… 查看全部问答> |
|
大家好: 我用IAR调试STR710的一个例子程序时,项目文件当Options-Debugger设置为软件仿真Simulator时编译和调试都没什么问题。当用第三方仿真器(Third-Party Driver为万利的STLINK仿真器),并进行相应的设置时出现了如下的 ...… 查看全部问答> |
|
要用DE2开发板上面插一个无线收发芯片 进行数据接收 请问芯片的驱动程序是写C程序还是写verilog程序啊 我问了不同的人 给我不同的答案 我自己也搞不清啊 我是初学的… 查看全部问答> |
|
提问:IAR Embedded Workbench出现的编译错误提示! 我用IAR Embedded Workbench编译器 出现错误 main.c Fatal Error[Cp001]: Copy protection check, No valid license found for this product [20] Error while running C/C++ compiler 请问是什么原因? 谢谢… 查看全部问答> |




