STM32F103和STM32F401的ADC多通道采集DMA输出

发布者:风暴使者最新更新时间:2021-08-27 来源: eefocus关键字:STM32F103  STM32F401  ADC  多通道采集 手机看文章 扫描二维码
随时随地手机看文章

使用STM32F103和STM32F401CCU6对双轴摇杆(两个电压通道)进行ADC采样并通过DMA读取数值


STM32 ADC(模数转换)工作模式

单次转换模式

In Single Conversion mode, the ADC does one conversion. This mode is started either by setting the ADON bit in the ADC_CR2 register (for a regular channel only) or by an external trigger (for a regular or injected channel), while the CONT bit is 0. Once the conversion of the selected channel is complete:


If a regular channel was converted:

– The converted data is stored in the 16-bit ADC_DR register

– The EOC (End Of Conversion) flag is set

– and an interrupt is generated if the EOCIE is set.

If an injected channel was converted:

– The converted data is stored in the 16-bit ADC_DRJ1 register

– The JEOC (End Of Conversion Injected) flag is set

– and an interrupt is generated if the JEOCIE bit is set.

The ADC is then stopped.


连续转换模式

In continuous conversion mode, ADC starts another conversion as soon as it finishes one. This mode is started either by an external trigger or by setting the ADON bit in the ADC_CR2 register, while the CONT bit is 1. After each conversion:


If a regular channel was converted:

– The converted data is stored in the 16-bit ADC_DR register

– The EOC (End Of Conversion) flag is set

– An interrupt is generated if the EOCIE is set.

If an injected channel was converted:

– The converted data is stored in the 16-bit ADC_DRJ1 register

– The JEOC (End Of Conversion Injected) flag is set

– An interrupt is generated if the JEOCIE bit is set.


扫描模式

This mode is used to scan a group of analog channels. A single conversion is performed for each channel of the group. After each end of conversion, the next channel of the group is converted automatically. If the CONT bit is set, conversion does not stop at the last selected group channel but continues again from the first selected group channel.


When using scan mode, DMA bit must be set and the direct memory access controller is used to transfer the converted data of regular group channels to SRAM after each update of the ADC_DR register. The injected channel converted data is always stored in the ADC_JDRx registers.


非连续模式

This mode is enabled by setting the DISCEN bit in the ADC_CR1 register. It can be used to convert a short sequence of n conversions (n <=8) which is a part of the sequence of conversions selected in the ADC_SQRx registers. The value of n is specified by writing to the DISCNUM[2:0] bits in the ADC_CR1 register.


When an external trigger occurs, it starts the next n conversions selected in the ADC_SQRx registers until all the conversions in the sequence are done. The total sequence length is defined by the L[3:0] bits in the ADC_SQR1 register.


读取ADC结果的几种方式

The Polling Method

It’s the easiest way in code in order to perform an analog to digital conversion using the ADC on an analog input channel. However, it’s not an efficient way in all cases as it’s considered to be a blocking way of using the ADC. As in this way, we start the A/D conversion and wait for the ADC until it completes the conversion so the CPU can resume processing the main code.


中断模式

The interrupt method is an efficient way to do ADC conversion in a non-blocking manner, so the CPU can resume executing the main code routine until the ADC completes the conversion and fires an interrupt signal so the CPU can switch to the ISR context and save the conversion results for further processing.


However, when you’re dealing with multiple channels in a circular mode or so, you’ll have periodic interrupts from the ADC that are too much for the CPU to handle. This will introduce jitter injection and interrupt latency and all sorts of timing issues to the system. This can be avoided by using DMA.


DMA方式

Lastly, the DMA method is the most efficient way of converting multiple ADC channels at very high rates and still transfers the results to the memory without CPU intervention which is so cool and time-saving technique.


STM32F103C8T6的代码实现

管脚与ADC的映射关系


PA0:7 ADC1_IN0:7

PB0 ADC1_IN8

PB1 ADC1_IN9

实现两个通道电压采集到DMA


确定要采集的信号通道数量, 每个信号通道要保留的采样数, 比如下面的例子中是2个通道, 每个通道4个采样

根据上面的数量得到ARRAYSIZE, 声明用于DMA的内存变量 __IO uint16_t ADCConvertedValue[ARRAYSIZE]

初始化时钟: ADC1, GPIOA, DMA1

初始化GPIOA用于采集的两个pin

初始化ADC1

初始化DMA1

代码


#include

#include "timer.h"

#include "usart.h"


#define ARRAYSIZE 2*4

__IO uint16_t ADCConvertedValue[ARRAYSIZE];


void RCC_Configuration(void)

{

  /* ADCCLK = PCLK2/4 */

  RCC_ADCCLKConfig(RCC_PCLK2_Div4); 

  /* Enable peripheral clocks ------------------------------------------------*/

  /* Enable DMA1 clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  /* Enable ADC1 and GPIOC clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

}


void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure PA.00 (ADC Channel0) as analog input -------------------------*/

  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0 | GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}


int main(void)

{

  SystemInit();

  Systick_Init();

  USART_Configuration();


  /* System clocks configuration ---------------------------------------------*/

  RCC_Configuration();


  /* GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

  

  /* ADC1 configuration ------------------------------------------------------*/

  ADC_InitTypeDef ADC_InitStructure;

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

  //We will convert multiple channels

  ADC_InitStructure.ADC_ScanConvMode = ENABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

  //right 12-bit data alignment in ADC data register

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  // Set it to the number of channels

  ADC_InitStructure.ADC_NbrOfChannel = 2;

  ADC_Init(ADC1, &ADC_InitStructure);


  /* ADC1 regular channel0 configuration, rank decides the order in ADCConvertedValue, start from 1 */

  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_41Cycles5);

  /* ADC1 regular channel1 configuration */

  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_41Cycles5);


  /* Enable ADC1 DMA */

  ADC_DMACmd(ADC1, ENABLE);

  

  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);


  /* Enable ADC1 reset calibration register */   

  ADC_ResetCalibration(ADC1);

  /* Check the end of ADC1 reset calibration register */

  while(ADC_GetResetCalibrationStatus(ADC1));


  /* Start ADC1 calibration */

  ADC_StartCalibration(ADC1);

  /* Check the end of ADC1 calibration */

  while(ADC_GetCalibrationStatus(ADC1));

     

  /* Start ADC1 Software Conversion */ 

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);


  /* DMA1 channel1 configuration ----------------------------------------------*/

  DMA_InitTypeDef DMA_InitStructure;

  DMA_DeInit(DMA1_Channel1);

  // ADC1_DR_Address    ((uint32_t)0x4001244C)

  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR);

  DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)ADCConvertedValue;

  /* Direction:

      DMA_DIR_PeripheralSRC:from peripheral, 

      DMA_DIR_PeripheralDST:to peripheral

  */

  DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;

  /* Specifies the buffer size, in data unit, of the specified Stream. 

     The data unit is equal to the configuration set in DMA_PeripheralDataSize 

     or DMA_MemoryDataSize members depending in the transfer direction. 

     Set it to the number of channels

  */

  DMA_InitStructure.DMA_BufferSize         = ARRAYSIZE;

  DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;

  // Specifies whether the memory address register should be incremented or not

  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;

  // Priority among DMA channels

  DMA_InitStructure.DMA_Priority           = DMA_Priority_High;

  // From Memory to Memory

  DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  /* Enable DMA1 channel1 */

  DMA_Cmd(DMA1_Channel1, ENABLE);


  while(1) {

    for (u8 i = 0; i < ARRAYSIZE; i++) {

      printf("%d ", *(ADCConvertedValue + i));

    }

    printf("rn");


    Systick_Delay_ms(500);

  }

}


void ADC1_IRQHandler(void)

{

  ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);

  ADC_SoftwareStartConvCmd(ADC1,ENABLE);

}


STM32F401CCU6的代码实现

只有1个16通道ADC. One 12-bit analog-to-digital converter is embedded and shares up to 16 external channels, performing conversions in the single-shot or scan mode. In scan mode, automatic conversion is performed on a selected group of analog inputs. The ADC can be served by the DMA controller. An analog watchdog feature allows very precise monitoring of the converted voltage of one, some or all selected channels. An interrupt is generated when the converted voltage is outside the programmed thresholds.

To synchronize A/D conversion and timers, the ADCs could be triggered by any of TIM1, TIM2, TIM3, TIM4 or TIM5 timer.


管脚与ADC的映射关系


PA0:7 ADC1_IN0:7

PB0 ADC1_IN8

PB1 ADC1_IN9

PC0:5 ADC1_IN10:15

因为F401CCU6的PC口只有PC13,PC14,PC15, 所以可以用的ADC只有ADC1_IN0 - IN9

[1] [2]
关键字:STM32F103  STM32F401  ADC  多通道采集 引用地址:STM32F103和STM32F401的ADC多通道采集DMA输出

上一篇:STM32 ADC学习
下一篇:STM32学习笔记-PWM波形输出

推荐阅读最新更新时间:2024-10-30 22:15

stm32f407之三ADC交替采样(操作寄存器)
stm32f407之三ADC交替采样(操作寄存器) 三ADC交替采样 在多ADC模式中,ADC1为主,ADC2或ADC3为从,交替或者同时触发,工作模式取决于ADC_CCR寄存器的MULTI 。 多ADC模式中,转换后的数据可以多模式的数据寄存器(ADC_CDR)中读取。状态可以在多模式的状态寄存器(ADC_CSR)读取。 多ADC模式下的DMA传输方式: 方式1:每个AD转换完都发出DMA请求,多模式的数据寄存器(ADC_CDR)用低位保存转换结果。 1st request: ADC_CDR = ADC1_DR 2nd request: ADC_CDR = ADC2_DR 3rd request: ADC_CDR =
[单片机]
STM32学习笔记:ADC理解
ADC 简介 12 位 ADC 是逐次趋近型模数转换器。它具有多达 19 个复用通道,可测量来自 16 个外部 源、两个内部源和 VBAT 通道的信号。这些通道的 A/D 转换可在单次、连续、扫描或不连续 采样模式下进行。ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。 ADC 主要特性 可配置 12 位、10 位、8 位或 6 位分辨率 ● 在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断 ● 单次和连续转换模式 ● 用于自动将通道 0 转换为通道“n”的扫描模式 ● 数据对齐以保持内置数据一致性 ● 可独立设置各通道采样时间 ● 外部触发器选项,可为规则转换和注入转换配置极性
[单片机]
STM32学习笔记:<font color='red'>ADC</font>理解
单片机外围模块漫谈之二,如何提高ADC转换精度
在此我们简要总结一下ADC的各种指标如何理解,以及从硬件到软件都有哪些可以采用的手段来提高ADC的转换精度。 1.ADC指标 除了分辨率,速度,输入范围这些基本指标外,衡量一个ADC好坏通常会用到以下这些指标:失调误差,增益误差,微分非线性,积分非线性,信噪比,信纳比,有效位数,总谐波失真。让我们以下图为例来看一下这些指标的意义。 LSB 参数中经常用LSB作为单位,比如说差分非线性为2 LSB。这究竟是多大一个值呢?为了简单起见,我们以一个3bit分辨率,满量程为5V的ADC为例。1个LSB对应的电压大小为5V/7=714mV。如果是8bit分辨率,那么1个LSB对应5/255=19mV。 图中横轴为输入电压Vin增
[单片机]
单片机外围模块漫谈之二,如何提高<font color='red'>ADC</font>转换精度
STM32的ADC多通道DMA使用方法
类似的问题 为什么我采集5条通道的电压,而采集到的值却都是第一条的呢? 我什么时候需要使用DMA功能? Ⅰ 关于ADC的一些知识 STM32的ADC是一种12位逐次逼近型的模拟数字转换器。它有多达18条通道,可测量16个外部和2个内部信号源。 各通道的A/D转换可以单次、连续、扫描或间断模式执行。 ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器ADC_DR中。 其实就是说,一个ADC,可检测18条通道,我们外接的只有16条。而结果只保存在一个寄存器ADC_DR中。 要使用ADC1采集多条通道,那么就需要对采集的通道进行分组排序。STM32的ADC可以把转换组织成两组:规则组和注
[单片机]
STM32的<font color='red'>ADC</font><font color='red'>多通道</font><font color='red'>DMA</font>使用方法
STM8单片机ADC应用(IAR)
STM8片上集成了10位逐次比较型模数转换器,在开发板上有个电位器接到了AIN3,但没有可以显示数据的LED数码管或LCD液晶显示屏,怎么办呢?可以把AD采集数据通过UART发送到电脑上显示。 #i nclude void CLK_init(void) { CLK_CKDIVR = 0x08; // 16M内部RC经2分频后系统时钟为8M } void GPIO_init(void) { PD_DDR = 0x08; // 配置PD端口的方向寄存器PD3输出 PD_CR1 = 0x08; // 设置PD3为推挽输出 PD_CR2 = 0x80; // 使能PD7外部中断 } void EXTI_init(void) { EXT
[单片机]
高速模数转换器的转换误差率解密
高速模数转换器(ADC)存在一些固有限制,使其偶尔会在其正常功能以外产生罕见的转换错误。但是,很多实际采样系统不容许存在高ADC转换误差率。因此,量化高速模数转换误差率(CER)的频率和幅度非常重要。 高速或GSPS ADC(每秒千兆采样ADC)相对稀疏出现的转换错误不仅造成其难以检测,而且还使测量过程非常耗时。该持续时间通常超出毫秒范围,达到几小时、几天、几周甚至是几个月。为了帮助消减这一耗时测试负担,可以在一定 置信度 的确定性情况下估算误差率,而仍然保持结果的质量。 误码率(BER)与转换误差率 与串行或并行数字数据传输中BER的数字等效值类似,CER是转换错误数与样本总数之比。但是,BER和CER之间有一些截然不同之
[电源管理]
高速<font color='red'>模数转换器</font>的转换误差率解密
基于STM32F103的深海远程电机控制系统
深海电机控制系统是深海科学考察、地质勘探、生物资源采集、深海打捞等深海作业中的一项关键技术, 使电机在深海的复杂环境中高效、可靠地运行具有重要的意义。目前, 在我国的深海科学考察中,通常采用有刷直流电机作为动力来源, 水下锂电池为其供电。由于锂电池价格昂贵且需要不时的对其进行充电, 严重影响了有效作业时间, 所以, 采用水上供电即远程控制的方式有很大的实际意义。另一方面,有刷直流电机因长时间侵泡在高压油中, 加上深海作业环境的恶劣, 电刷和换相器很容易损坏。而永磁同步电机利用电子换相代替了机械换相, 不但具有直流电机的调速性能, 而且体积小、效率高。永磁同步电机的转子采用永磁体, 所以省去了励磁电路, 因而具有更高的功率因素。近几
[单片机]
基于<font color='red'>STM32F103</font>的深海远程电机控制系统
凌力尔特的超低功率、14 位 150Msps ADC
  凌力尔特公司 (Linear Technology Corporation) 推出超低功率 14 位、150Msps 模数转换器 (ADC) LTC2262,该器件仅消耗 149mW 功率,这低于同类解决方案功耗的 1/3。这种新的基准使得那些受限于严格功率预算的便携式应用能够扩展其性能,并为 3G/4G LTE 和 WiMAX 基站设备提供较高的工作效率和减低经常性运作成本。除了消耗低得多的功率,LTC2262 还集成了两种独特的功能,以在甚至良好的布局做法也可能失效的情况下减少数字反馈。这些特点加之低功率可减轻在多种应用中采用高速 ADC 完成设计任务的负担,这些应用包括便携式医疗成像和超声、便携式测试和仪表、非破坏性测试
[模拟电子]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved