引言

本应用笔记提供如何在APM32F4xx系列上配置和应用ADC接口的指南,包括接口框图、代码实现和应用方法。

APM32F4xx微控制器内置最多三个12位的逐次逼近型ADC,三个ADC共享最多21个外部输入通道和3个内部通道,并提供自校准功能。内部通道分别提供测量芯片内置温度传感器电压、参考电压以及备份电源电压的功能。各个A/D转换通道支持单次、连续、扫描和间断的转换方式。ADC转换的结果可以设置成左对齐或右对齐来存储在16位的数据寄存器中,并且支持DMA访问和设置模拟看门狗

ADC简介

模数转换器,ADC(Analog to Digital Converter),是一个将模拟信号转换为数字信号的器件(电路),例如将温度、湿度、压力、位置等信息转换为数字信号。但由于数字信号本身不具有实际意义,仅仅表示一个相对大小。所以ADC都需要一个参考模拟量(REF)作为转换的标准。

图 1 ADC框图

ADC分类

ADC按工作原理可以分成直接ADC和间接ADC。主要有以下几种:

并联比较型ADC;

逐次逼近型ADC;

双积分型ADC。

其中逐次逼近型ADC是一种直接ADC。由于其采样速率中等,分辨率中等,且位数较多时使用元器件较少等原因(成本较低),所以被广泛应用于集成ADC中。

图 2 ADC分类

A/D转换原理

A/D转换的作用是将时间、幅值连续的模拟信号转换为时间、幅值离散的数字信号。所以,A/D转换一般要经过采样保持量化编码四个过程。

A/D转换步骤

采样和保持

采样是指在时间上将模拟信号离散化,即是将时间上连续的信号转为一系列等时间间隔的信号离散序列。其中离散信号脉冲的幅度取决于输入模拟量。

量化和编码

量化是用有限个幅度值近似原来连续变化的幅度值,把模拟信号的连续幅度变为有限数量的有一定间隔的离散值。而编码则是按照一定的规律,把量化后的值用二进制数字表示。下图列举了12bits ADC的FSR为3.3V时的量化到编码的过程。其中:

N:分辨率,用于对输入进行量化的位数。理论上,n位输出的ADC能区分2n个不同等级的模拟输入电压。如下图所示,能分辨的最小输入电压步长LSB = FSR / 2n = 806uV;

FSR: Full-Scale Range,满量程;

LSB: Least Significant Bit,最低有效位;

MSB: Most Significant Bit,最高有效位。

图 3 量化和编码

转换时间

转换时间是指ADC从转换控制信号触发开始,到输出端得到稳定的数字信号所经过的时间。该时间受ADC类型、ADC时钟和外部输入阻抗等因素影响。

APM32中的ADC

APM32中的ADC是逐次逼近型ADC(Successive Approximation ADC),是逐个产生比较电压VREF,并逐次与输入电压分别比较,以逐渐逼近的方式进行A/D转换的。

SAR ADC的转换原理是把输入的模拟信号按规定的时间间隔采样(采样),并与一系列标准的数字信号相比较,数字信号逐次收敛,直至两种信号相等为止(量化),最后输出代表此信号的二进制数(编码)。

ADC的结构

结构上主要包括采样保持电路(S/H),比较器(COMPARATOR,COMP),SAR逻辑控制电路、时钟(CLOCK)和时序(TIMING)控制电路及DAC电路。

图 4 ADC结构

S/H电路

被采样的脉冲宽度一般是很短的,在下一个采样脉冲到来之前,要暂时保持所采得的样值脉冲幅度,以便进行后续转换。所以,在采样电路之后要加保持电路。下图是一个简单的采样保持电路配置框图。

图 5 S/H电路

DAC电路

大多SAR ADC的DAC都使用电容式DAC来提供内在的跟踪/保持功能。电容式DAC是采用电荷再分配原理来产生模拟输出电压的。电容式DAC由N个具有二进制权重值的电容器阵列再加上一个“虚拟LSB”电容器组成。

转换步骤

转换步骤数等于 ADC的分辨率,比如10bits ADC就有10个转换步骤,每个 ADC 时钟产生一个数据位。以下步骤以10bits ADC为例。采样和保持的状态,可以参考上述的S/H等效电路来理解。下面着重看下量化和编码的状态。

量化和编码状态

该状态下,每个 ADCCLK 执行一个步骤,每一步完成后 ADC 输出一位数。采用二分法进行逐次逼近到 ADC 的精度(位数)。整个转换过程如下图所示。

图 6 量化和编码状态

转换例子

比如2.5V输入到以3.3V为参考电压的SAR ADC中,则转换过程如下所示。

第一个逼近步骤时,MSB先设置为1。DAC以1/2 REF去和VIN比较,若VIN > 1/2 REF,则保持MSB = 1(反之则MSB = 0)。等待下一个ADCCLK,执行下一步。

图 7 ADC转换逼近步骤1

第二个逼近步骤时,MSB往后移动1个bit,再以3/4 REF去和VIN进行比较,若VIN > 3/4 REF,则保持MSB = 1(反之则MSB = 0)。等待下一个ADCCLK,执行下一步,一直到所有bit确定,然后输出编码值。

图 8 ADC转换逼近步骤2

转换时间

APM32F4xx中的ADC转换时间 = 采样周期 + 转换周期。

采样周期

采样周期设置决定,要注意的是,该值需要和外部电路的输入阻抗匹配。从而保证在采用阶段,采样保持电容有足够的时间充电。

转换周期

该值取决于ADC的转换精度,APM32F4xx的SAR ADC默认为12bits,可配置为12、10、8、6bits。

表格 1 ADC精度和转换周期关系

序号

ADC精度

转换周期

1

12 bits

12 x ADCCLK

2

10 bits

10 x ADCCLK

3

8 bits

8 x ADCCLK

4

6 bits

6 x ADCCLK

转换数值

ADC 转换的数值 = (VIN x 2n) / VREF,n为ADC的分辨率。以上述12bits的ADC为例,则

ADC 转换的数值 = (VIN x 4096) / VREF。

ADC的配置和应用

转换周期

输入通道

MINI Board已经将部分ADC的通道通过排针接出,可以根据设计需求使用相关IO。ADC采样容易受外接干扰,使用时注意引脚间的抗干扰设计,以及避免ADC引脚和其他功能电路共用的情况。

电压输入范围

ADC的电压输入范围为VREF- ~ VREF+,MINI板上的VSSA和VREF-接入GND,而VDDA和VREF+接入VDD,所以在MINI板上的ADC电压输入范围是0V ~ 3.3V。

软件设计

软件设计上只讲解关键的配置,部分查询和逻辑代码未设计,详细可直接参考本应用说明配套的例程。

ADC初始化结构体

ADC_Config_T结构体定义在APM32F4xx_adc.h文件中,具体定义如下:

/**

* @brief ADC configuration Mode

*/

typedef struct

{

ADC_RESOLUTION_T    resolution;

uint8_t             scanConvMode;

uint8_t             continuousConvMode;

ADC_EXT_TRIG_EDGE_T extTrigEdge;

ADC_EXT_TRIG_CONV_T extTrigConv;

ADC_DATA_ALIGN_T    dataAlign;

uint8_t             nbrOfChannel;

} ADC_Config_T;

结构体中的参数含义:

resolution:用于配置ADC的分辨率,可以配ADC的分辨率为12bit、10bit、8bit和6bit。如本应用说明SAR ADC转换原理所述,ADC的分辨率配置越高,相对的转换时间也越长;

scanConvMode:用于配置是否使扫描模式,一般单通道A/D转换应用时配置为DISABLE,多通道A/D转换应用时配置为ENABLE;

continuousConvMode:用于配置是单次转换,还是启用自动连续转换模式;

extTrigEdge:用于配置外部触发的极性,如果未使能外部触发,可配置为ADC_EXT_TRIG_EDGE_NONE;

extTrigConv:用于配置外部触发源;

dataAlign:用于配置ADC转换结果的数据对齐方式,一般按照习惯,我们配置为右对齐模式;

nbrOfChannel:用于配置A/D转换通道的数目。

ADC通用初始化结构体

ADC_ CommonConfig _T结构体定义在APM32F4xx_adc.h文件中,具体定义如下:

/**

* @brief ADC Common Init structure definition

*/

typedef struct

{

ADC_MODE_T         mode;

ADC_PRESCALER_T    prescaler;

ADC_ACCESS_MODE_T  accessMode;

ADC_TWO_SAMPLING_T twoSampling;

} ADC_CommonConfig_T;

结构体中的参数含义:

mode:用于配置ADC的工作模式,有独立模式、双重模式和三重模式的配置项可供选择;

prescaler:用于配置ADC时钟的分频系数,ADC时钟由PCLK2提供。PCLK2除以prescaler就是ADC的时钟;

accessMode:用于配置DMA模式;

twoSampling:用于配置两个采样阶段间的延迟。

单通道转换软件设计

以“ADC_ContinuousConversion”例程为例。

配置ADC

开启GPIO时钟后,配置GPIO为模拟输入模式。

/*!

* @brief       ADC Init

*

* @param       None

*

* @retval      None

*/

void ADC_Init(void)

{

GPIO_Config_T   gpioConfig;

ADC_Config_T    adcConfig;

/** Enable GPIOA clock */

RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);

/** ADC channel 0 configuration */

GPIO_ConfigStructInit(&gpioConfig);

gpioConfig.mode    = GPIO_MODE_AN;

gpioConfig.pupd    = GPIO_PUPD_NOPULL;

gpioConfig.pin     = GPIO_PIN_0;

GPIO_Config(GPIOA, &gpioConfig);

配置ADC工作方式,开启连续转换模式。

/** Enable ADC clock */

RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);

/** ADC configuration */

ADC_Reset();

ADC_ConfigStructInit(&adcConfig);

adcConfig.resolution          = ADC_RESOLUTION_12BIT;

adcConfig.continuousConvMode  = ENABLE;

adcConfig.dataAlign           = ADC_DATA_ALIGN_RIGHT;

adcConfig.extTrigEdge         = ADC_EXT_TRIG_EDGE_NONE;

adcConfig.scanConvMode        = DISABLE;

ADC_Config(ADC1, &adcConfig);

配置开启ADC中断,使能ADC并软件触发转换。

/** ADC channel 0 Convert configuration */

ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_112CYCLES);

/** Enable complete conversion interupt */

ADC_EnableInterrupt(ADC1, ADC_INT_EOC);

/** NVIC configuration */

NVIC_EnableIRQRequest(ADC_IRQn, 1, 1);

/** Enable ADC */

ADC_Enable(ADC1);

/** ADC start conversion */

ADC_SoftwareStartConv(ADC1);

}

ADC中断服务函数

检测到转换完成后,回调该中断服务函数。并读取此时的ADC转换值,然后将其转换成对应电压值,该值受量化误差和硬件抗干扰能力所影响。这里转换出来的电压单位是mV。

/*!

* @brief       ADC interrupt service routine

*

* @param       None

*

* @retval      None

*/

void ADC_Isr(void)

{

uint16_t adcData = 0;

uint16_t voltage = 0;

if (ADC_ReadStatusFlag(ADC1, ADC_FLAG_EOC))

{

ADC_ClearStatusFlag(ADC1, ADC_FLAG_EOC);

adcData = ADC_ReadConversionValue(ADC1);

voltage = (adcData * 3300) / 4095;

printf("\r\n voltage : %d mV\r\n", voltage);

}

}

多通道扫描软件设计

以“ADC_MultiChannelScan”例程为例。

定义公共信息

这里定义了本样例采样的通道数为3个通道,并定义了将用于DMA存储ADC各通道扫描数据的数组adcData[ADC_CH_SIZE]。另外还宏定义了ADC规则数据寄存器的地址为ADC_DR_ADDR。以上这些信息都会用于后续配置和应用中。

/** save adc data*/

#define ADC_CH_SIZE         3

#define ADC_DR_ADDR         ((uint32_t)ADC1_BASE + 0x4C)

uint16_t adcData[ADC_CH_SIZE];

配置DMA

将ADC的规则寄存器地址设置为DMA访问的寄存器地址,设置寄存器递增并规定buffer的大小为3,最后开启循环模式。

DMA的不同通道和数据流规定了其所属的外设,使用时要注意。

/*!

* @brief       DMA Init

*

* @param       None

*

* @retval      None

*/

void DMA_Init(void)

{

DMA_Config_T dmaConfig;

RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2);

dmaConfig.peripheralBaseAddr = ADC_DR_ADDR;

dmaConfig.memoryBaseAddr = (uint32_t)&adcData;

dmaConfig.dir = DMA_DIR_PERIPHERALTOMEMORY;

dmaConfig.bufferSize = ADC_CH_SIZE;

dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;

dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;

dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD;

dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_HALFWORD;

dmaConfig.loopMode = DMA_MODE_CIRCULAR;

dmaConfig.priority = DMA_PRIORITY_HIGH;

dmaConfig.fifoMode = DMA_FIFOMODE_DISABLE;

dmaConfig.fifoThreshold = DMA_FIFOTHRESHOLD_HALFFULL;

dmaConfig.memoryBurst = DMA_MEMORYBURST_SINGLE;

dmaConfig.peripheralBurst = DMA_PERIPHERALBURST_SINGLE;

dmaConfig.channel = DMA_CHANNEL_0;

DMA_Config(DMA2_Stream0,&dmaConfig);

DMA_Enable(DMA2_Stream0);

}

配置ADC

和单通道转换配置顺序一样,首先将要扫描的三个通道开启相应时钟和配置为模拟输入模式。

/*!

* @brief       ADC Init

*

* @param       None

*

* @retval      None

*/

void ADC_Init(void)

{

GPIO_Config_T           gpioConfig;

ADC_Config_T            adcConfig;

ADC_CommonConfig_T      adcCommonConfig;

/** Enable GPIOA clock */

RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);

/** ADC channel 0 configuration */

GPIO_ConfigStructInit(&gpioConfig);

gpioConfig.mode    = GPIO_MODE_AN;

gpioConfig.pupd    = GPIO_PUPD_NOPULL;

gpioConfig.pin     = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;

GPIO_Config(GPIOA, &gpioConfig);

接着是ADC的通用配置。

/** Enable ADC clock */

RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);

/** ADC configuration */

ADC_Reset();

adcCommonConfig.mode            = ADC_MODE_INDEPENDENT;

adcCommonConfig.prescaler       = ADC_PRESCALER_DIV2;

adcCommonConfig.accessMode      = ADC_ACCESS_MODE_DISABLED;

adcCommonConfig.twoSampling     = ADC_TWO_SAMPLING_20CYCLES;

ADC_CommonConfig(&adcCommonConfig);

然后是ADC工作模式的配置,这里配置为连续扫描模式,并设置转换通道数为3个。

ADC_ConfigStructInit(&adcConfig);

adcConfig.resolution            = ADC_RESOLUTION_12BIT;

adcConfig.scanConvMode          = ENABLE;

adcConfig.continuousConvMode    = ENABLE;

adcConfig.dataAlign             = ADC_DATA_ALIGN_RIGHT;

adcConfig.extTrigEdge           = ADC_EXT_TRIG_EDGE_NONE;

adcConfig.extTrigConv           = ADC_EXT_TRIG_CONV_TMR1_CC1;

adcConfig.nbrOfChannel          = ADC_CH_SIZE;

ADC_Config(ADC1, &adcConfig);

配置各通道的转换顺序及采样周期。

/** ADC channel Convert configuration */

ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0,

ADC_SAMPLETIME_480CYCLES);

ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_1, 2, ADC_SAMPLETIME_480CYCLES);

ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_2, 3, ADC_SAMPLETIME_480CYCLES);

最后开启DMA、使能ADC并触发转换。到这里多通道扫描的配置就完成了,接着直接轮询ADC转换值存储的数组即可获得各通道的扫描值。

/** Config DMA*/

DMA_Init();

/** Enable ADC DMA Request*/

ADC_EnableDMARequest(ADC1);

/** Enable ADC DMA*/

ADC_EnableDMA(ADC1);

/** Enable ADC */

ADC_Enable(ADC1);

/** ADC start conversion */

ADC_SoftwareStartConv(ADC1);

}

提高采样精度的硬件方法

1. 保证参考电压噪声最小化;

2. IO引脚串扰最小化;

3. 加入屏蔽减少EMI;

4. PCB将模拟和数字分开布局和铺设。

提高采样精度的软件方法

采样平均

在硬件抗干扰能力不足的情况下,我们可以牺牲采用速率,采用软件方法进行滤波,从而得到更加稳定的采样值。

数字信号滤波

可通过数字低通、高通等滤波器进行软件滤波。比如知道被测信号中的噪声来自50 Hz供电线,通过适当的数字滤波,可以只抑制50 Hz频率并传输无此噪声的数据信号。

ADC软件校准

如果采样值较为固定,但离目标值相差大,还可以利用线性拟合(线性校准曲线)的方式让采样值更接近目标值。

采样

首先基于标准源表采样足够多的点,如下表(点数越多,拟合越准确)。

表格 2 采样表

序号

采样值(mV)

目标值(mV)

1

96.7

100

2

194.5

200

3

498.8

500

4

796

800

5

1495

1500

拟合

在数学工具(Matlab或Excel等)中做线性拟合(线性、多项式、指数皆可),得到校准公式和相关系数R值。

图 9 拟合

校准

用拟合步骤中得到的校准公式对采样值进行校准。

表格 3采样表

序号

采样值(mV)

目标值(mV)

校准值(mV)

1

96.7

100

100.1

2

194.5

200

197.9

3

498.8

500

502.5

4

796

800

799.9

5

1495

1500

1499.4

【应用笔记】APM32F4xx_ADC应用笔记相关推荐

  1. 《算法笔记》学习笔记(1)

    <算法笔记>学习笔记(1) 2021/4/7号 晚上21:36开始学习 第二章 c++/c快速入门 有的时候不要在一个程序中同时使用cout 和 printf 有的时候会出现问题. 头文件 ...

  2. 涂书笔记-让读书笔记不再困难

    今天晴空万里,没有一丝云彩,阳光也暖暖的,照得人心头亮堂堂的.而我趁着五一这放假的时光,补充一下精神的食粮,倚靠在那略微倾斜的凳子上,阅读着我喜欢的书.看书看到宋真宗赵恒,想起他曾说"富家不 ...

  3. 适合写笔记的文本笔记管理工具——Keep It for Mac!

    一款非常适合写笔记的文本笔记管理工具--Keep It for Mac,保存网页链接,存储文档,图像或任何类型的文件,并再次找到它们.你可以使用文件按层次结构组织事物,选择一个文件夹以查看它及其子文件 ...

  4. Joplin笔记 android,把笔记还给用户,可以选择自己存储位置的笔记应用#Joplin

    把笔记还给用户,可以选择自己存储位置的笔记应用#Joplin 2020-06-15 18:34:44 12点赞 96收藏 13评论 各种「云笔记」现在已经为人所熟知.在充分运用「云技术」的今天,另一股 ...

  5. 小红书达人笔记与素人笔记的区别,对号入座选达人

    接触小红书的人一定对小红书达人和笔记这两样东西不陌生,但是笔记也分达人笔记和素人笔记.那么小红书达人笔记与素人笔记的区别是什么?各自适用于哪些场景?今天就来和大家好好分享一下其中的奥妙. 一.小红书达 ...

  6. TED阅读笔记,学习笔记

    TED阅读笔记,学习笔记,大约200集 每日一读,一起来学英语吧 自用,喜欢的帮忙点个赞

  7. Vue 2.x 常用知识点笔记(万字笔记)

    Vue 2.x 笔记 常用知识点笔记,有错误欢迎指点哦~ 字数超过了一万字,得细品 目录 Vue 2.x 笔记 1.新建Vue实例 2.阻止生成生产提示 3.模板语法 3.1 插值语法 3.2 指令语 ...

  8. Joplin笔记 android,把笔记还给用户「Joplin」可以选择自己存储位置的笔记应用

    各种「云笔记」现在已经为人所熟知.在充分运用「云技术」的今天,另一股新潮流也在逐渐涌动. 这股潮流认为:「应该把笔记从云端还给用户」.具体来说:用户不要将笔记信息保存在「云笔记」大厂的服务器上,新潮流 ...

  9. 小红书商业笔记与普通笔记区别是什么?小红书笔记有哪几种

    主攻单一平台,如何迅速打造爆文.针对软文发布类别的选择,小红书商业笔记与普通笔记区别究竟是什么,今天为大家带来的详细分析,告诉你该如何用最少的成本,做出"爆文". 1.小红书的笔记 ...

  10. 本地笔记软件_笔记软件obsidian重大更新

    obsidian是一个笔记软件,之前写了篇obsidian的介绍 https://zhuanlan.zhihu.com/p/212204160​zhuanlan.zhihu.com 这次obsidia ...

最新文章

  1. 《响应式Web图形设计》一13.2 缩放图像带来的问题
  2. 谈谈 Tomcat 请求处理流程
  3. P16对member进行代码生成时,访问端口出现This application has no explicit mapping for /error, so you are seeing this
  4. java常考设计模式_java笔试常考的几种设计模式
  5. 双十一!!作为程序员的你该如何拥有个人服务器和域名呢?
  6. 当代开发者的六大真实现状,你被哪一个场景“戳中”了?
  7. 获取div中的内容写法
  8. android bool转字符串,Android 知识点——当json传入字符串,使用Boolean接收时,GSON会将其转换为false...
  9. 190529每日一句,放胆去梦想,努力去奋斗
  10. Spring源码下载以及构建技巧
  11. Windows 7 专业版如何安装英文、中文语言包
  12. Win10—VMware15虚拟机安装教程
  13. 低层次数论书籍大杂烩
  14. win7 管理iphone日历_iPhone和Windows同步文件,这7个技巧让你的效率成倍增加
  15. 大脑中的CD19表达与CAR-T治疗关系
  16. 企鲸客scrm 渠道活码功能介绍及作用
  17. ibm服务器显示0 bf,IBM服务器常见服务器故障总结
  18. 主流RGBD数据集简介 2019.12.15
  19. 王者荣耀服务器怎么修改,王者荣耀常用英雄自定义攻略怎么设置 自定义攻略设置方法介绍...
  20. C语言打字游戏(无错误警告版)

热门文章

  1. [JZOJ3339]【NOI2013模拟】wyl8899和法法塔的游戏
  2. 自建CA然后颁发证书给搭建的httpd用
  3. Riverbed宣布收购领先的Wi-Fi网络提供商Xirrus
  4. VR和AR的区别是什么?-粤嵌教育
  5. MPEG压缩中的 I、B、P帧
  6. 走火入魔的macfans,披着mac皮的ubuntu macbuntu安装指南
  7. linux wrf软件安装,wrf安装
  8. 置信区间 VS 置信水平
  9. 朋友圈爱心拼图php源码_微信朋友圈九宫格爱心拼图怎么弄 拼图教程
  10. java跳转到ie_ie跳转chrome(ie浏览器点击链接跳转谷歌浏览器)