目录

01、ADC简介

02、STM32的ADC外设

03、STM32ADC框图讲解

04、触发源

05、转换周期

06、数据寄存器

07、中断

08、电压转换

09、电路图设计

10、代码设计


01、ADC简介

ADC是Analog-to-DigitalConverter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。

从STM32F207的数据手册中下图看到,STM32F207VC有3个精度为12bit的ADC控制器,有16个外部通道,而144脚的STM32F207Zx和176脚的STM32F207Ix因为带PF脚,所以多8个通道,为24个外部通道。各通道的A/D转换可以单次、连续、扫描或间断执行,ADC转换的结果可以左对齐或右对齐储存在16位数据寄存器中。

02、STM32的ADC外设

上面说到,STM32F207有3个12bit的ADC控制器,下文将以ADC3的通道10讲解。

首先我们确认下ADC外设所在的地址总线,从STM32F207数据手册中下图看到,ADC属于APB2总线下,APB2时钟频率是60MHz。具体STM32如果通过外部25M晶振得到的60MHz的APB2,请看《STM32F207时钟系统解析》。

对应GPIO,我们从STM32F207数据手册中看到,我们可以使用PC0作为ADC3的通道10。

这里需要说明的是,之前的文章使用其他外设时,比如《STM32PWM输出》中,寻找对应的管脚时,我们都是从STM32F207数据手册的Alternatefunctionmapping表中寻找,这是因为ADC对应的管脚使用的是Additionalfunctions,PWM对应的管脚使用的是Alternatefunctions。

区别是:

Additionalfunctions:附加,辅助功能,引脚被连接到其他模块使用,使用时直接普通配置即可,例如ADC的采用输入通道,配置为模拟输入。

Alternate functions:复用功能,即将IO口用作普通输入输出以外的功能,例如串口输入输出,使用时需要配置复用模式。

在之前的文章《STM32GPIO详解》中有如下介绍。

STM32标准外设库中有如下代码

typedef enum
{   GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */  GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */  GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */  GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
}GPIOMode_TypeDef;

其中GPIO_Mode_AF对应的就是Alternate functions:复用功能,GPIO_Mode_AN对应的就是Additional functions:附加,辅助功能。

03、STM32ADC框图讲解

下图是STM32ADC的结构框图,我们将其划分为7个部分进行讲解。

1、输入电压范围

ADC所能测量的电压范围就是VREF-≤ VIN ≤ VREF+,把VSSA 和VREF-接地,把VREF+和VDDA 接3V3,得到ADC的输入电压范围为:0~3.3V。

2、输入通道

ADC的信号时通过输入通道进入单片机内部的,单片机通过ADC模块将模拟信号转换为数字信号。上图标记②的部分显示了外部的16个通道,连接的GPIO,对应的关系如上面讲解的,需要在STM32F207数据手册的STM32F20xpin and ball definitions表格中寻找。实际上STM32还有内部通道,ADC1的通道 16连接到了芯片内部的温度传感器,Vrefint 连接到了通道17。ADC2的模拟通道 16和 17连接到了内部的VSS。

3、转换通道

外部的16个通道在转换时又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4路(注入通道貌似使用不多),下面简单介绍一下俩种通道:

规则通道

规则通道顾名思义就是,最平常的通道、也是最常用的通道,平时的ADC转换都是用规则通道实的。规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则组转换的总数应写入ADC_SQR1寄存器的L[3:0]中。

注入通道

注入通道是相对于规则通道的,注入通道可以在规则通道转换时,强行插入转换,相当于一个“中断通道”吧。当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执行完毕后,再回到之前规则通道进行转换。最多4个通道,注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转化的总数应写入ADC_JSQR寄存器的L[1:0]中。

一个ADC控制器有多个通道,这就涉及使用多个通道进行转换就涉及到一个先后顺序的问题了,毕竟规则转换通道只有一个数据寄存器。多个通道的使用顺序分为俩种情况:规则通道的转换顺序和注入通道的转换顺序。

规则通道转换顺序

规则通道中的转换顺序由三个寄存器控制:SQR1、SQR2、SQR3,它们都是32位寄存器。SQR寄存器控制着转换通道的数目和转换顺序,只要在对应的寄存器位SQx中写入相应的通道,这个通道就是第x个转换,通过SQR1寄存器就能了解其转换顺序在寄存器上的实现了。

注入通道转换顺序

和规则通道转换顺序的控制一样,注入通道的转换也是通过注入寄存器来控制,只不过只有一个JSQR寄存器来控制,控制关系如下:

需要注意的是,只有当JL=4的时候,注入通道的转换顺序才会按照JSQ1、JSQ2、JSQ3、JSQ4的顺序执行。当JL<4时,注入通道的转换顺序恰恰相反,也就是执行顺序为:JSQ4、JSQ3、JSQ2、JSQ1。

配置转换顺序的函数

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime)

04、触发源

ADC转换的输入、通道、转换顺序都已经说明了,但ADC转换是怎么触发的呢?就像通信协议一样,都要规定一个起始信号才能传输信息,ADC也需要一个触发信号来实行模/数转换。

其一就是通过直接配置寄存器触发,通过配置控制寄存器CR2的ADON位,写1时开始转换,写0时停止转换。在程序运行过程中只要调用库函数,将CR2寄存器的ADON位置1就可以进行转换,比较好理解。

另外,还可以通过内部定时器或者外部IO触发转换,也就是说可以利用内部时钟让ADC进行周期性的转换,也可以利用外部IO使ADC在需要时转换,具体的触发由控制寄存器CR2决定。

05、转换周期

可独立设置各通道采样时间

ADC会在数个ADCCLK周期内对输入电压进行采样,可使用ADC_SMPR1和ADC_SMPR2

寄存器中的SMP[2:0]位修改周期数。每个通道均可以使用不同的采样时间进行采样。

总转换时间的计算公式如下:

Tconv=采样时间+12个周期

示例:

ADCCLK = 30 MHz且采样时间=3个周期时:

Tconv= 3+12=15个周期=0.5us (APB2为60MHz时)

最小采样时间0.42us(ADC时钟=36MHz,采样周期为3周期下得到)。

06、数据寄存器

转换完成后的数据就存放在数据寄存器中,但数据的存放也分为规则通道转换数据和注入通道转换数据的。

规则数据寄存器

规则数据寄存器负责存放规则通道转换的数据,通过32位寄存器ADC_DR来存放。

注入数据寄存器

注入通道转换的数据寄存器有4个,由于注入通道最多有4个,所以注入通道转换的数据都有固定的存放位置,不会跟规则寄存器那样产生数据覆盖的问题。 ADC_JDRx是 32位的,低 16位有效,高 16位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由ADC_CR2的 11 位ALIGN 设置。

07、中断

可以产生4种中断

DMA溢出中断

当配置了DMA,且DMA溢出时产生中断

规则通道转换完成中断

规则通道数据转换完成之后,可以产生一个中断,可以在中断函数中读取规则数据寄存器的值。这也是单通道时读取数据的一种方法。

注入通道转换完成中断

注入通道数据转换完成之后,可以产生一个中断,并且也可以在中断中读取注入数据寄存器的值,达到读取数据的作用。

模拟看门狗事件

当输入的模拟量(电压)不再阈值范围内就会产生看门狗事件,就是用来监视输入的模拟量是否常。

08、电压转换

转换后的数据是一个12位的二进制数,我们需要把这个二进制数代表的模拟量(电压)用数字表示出来。比如测量的电压范围是0~3.3V,转换后的二进制数是x,因为12位ADC在转换时将电压的范围大小(也就是3.3)分为4096(2^12)份,所以转换后的二进制数x代表的真实电压的计算方法就是:

y=3.3* x / 4096

09、电路图设计

电路图很简单,可以在ADC引脚上输入不同的电压,也可以直接方便的使用滑动变阻器实现不同的电压变化。

10、代码设计

ADC外设配置的结构体

typedef struct
{uint32_t ADC_Resolution;                /*!< Configures the ADC resolution dual mode. This parameter can be a value of @ref ADC_resolution */                                   FunctionalState ADC_ScanConvMode;       /*!< Specifies whether the conversion is performed in Scan (multichannels) or Single (one channel) mode.This parameter can be set to ENABLE or DISABLE */ FunctionalState ADC_ContinuousConvMode; /*!< Specifies whether the conversion is performed in Continuous or Single mode.This parameter can be set to ENABLE or DISABLE. */uint32_t ADC_ExternalTrigConvEdge;      /*!< Select the external trigger edge andenable the trigger of a regular group. This parameter can be a value of @ref ADC_external_trigger_edge_for_regular_channels_conversion */uint32_t ADC_ExternalTrigConv;          /*!< Select the external event used to trigger the start of conversion of a regular group.This parameter can be a value of @ref ADC_extrenal_trigger_sources_for_regular_channels_conversion */uint32_t ADC_DataAlign;                 /*!< Specifies whether the ADC data  alignmentis left or right. This parameter can be a value of @ref ADC_data_align */uint8_t  ADC_NbrOfConversion;           /*!< Specifies the number of ADC conversionsthat will be done using the sequencer forregular channel group.This parameter must range from 1 to 16. */
}ADC_InitTypeDef;

ADC_Resolution:ADC 工作模式选择,ADC分辨率

ADC_ScanConvMode:ADC 扫描(多通道)或者单次(单通道)模式选择

ADC_ContinuousConvMode:ADC 单次转换或者连续转换选择

ADC_ExternalTrigConvEdge:ADC 外部触发极性配置

ADC_ExternalTrigConv:ADC 转换触发信号选择

ADC_DataAlign:ADC 数据寄存器对齐格式

ADC_NbrOfConversion:ADC转换通道数目

typedef struct
{uint32_t ADC_Mode;//多重ADC模式选择uint32_t ADC_Prescaler;  //ADC预分频                             uint32_t ADC_DMAAccessMode;   //DMA访问模式       uint32_t ADC_TwoSamplingDelay; //2个采样阶段之间的延迟
}ADC_CommonInitTypeDef;

ADC_CommonInitTypeDef用来配置ADC_CCR寄存器的相关参数

ADC外设和DMA配置代码

/*** @brief  ADC3 channel10 with DMA configuration* @param  None* @retval None*/
void ADC3_CH10_DMA_Config(void)
{ADC_InitTypeDef       ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;DMA_InitTypeDef       DMA_InitStructure;GPIO_InitTypeDef      GPIO_InitStructure;/* Enable ADC3, DMA2 and GPIO clocks ****************************************/RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);/* DMA2 Stream0 channel2 configuration **************************************/DMA_InitStructure.DMA_Channel = DMA_Channel_2;  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;DMA_InitStructure.DMA_BufferSize = 1;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;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_High;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);DMA_Cmd(DMA2_Stream0, ENABLE);/* Configure ADC3 Channel10 pin as analog input ******************************/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(GPIOC, &GPIO_InitStructure);/* ADC Common Init **********************************************************/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);/* ADC3 Init ****************************************************************/ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;ADC_InitStructure.ADC_ScanConvMode = DISABLE;ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;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 = 1;ADC_Init(ADC3, &ADC_InitStructure);/* ADC3 regular channel7 configuration *************************************/ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);/* Enable DMA request after last transfer (Single-ADC mode) */ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);/* Enable ADC3 DMA */ADC_DMACmd(ADC3, ENABLE);/* Enable ADC3 */ADC_Cmd(ADC3, ENABLE);
}

代码下载验证测试

硬件和软件开源地址:

https://github.com/strongercjd/STM32F207VCT6

点击查看本文所在的专辑,STM32F207教程

关注公众号,第一时间收到文章更新。评论区不能及时看到,需要交流可以到公众号沟通

STM32 ADC详解相关推荐

  1. STM32—ADC详解

    1.ADC简介 STM32F103 系列最少都拥有 2 个 ADC,我们选择的 STM32F103RCT 包含有 3 个 ADC,STM32的最大转换速率为1Mhz,也就是转换时间为1us,除此之外, ...

  2. stm32位操作详解

    stm32位操作详解 STM32位操作原理 思想:把一个比特分成32位,每位都分配一个地址,这样就有32个地址,通过地址直接访问. 位操作基础 位运算 位运算的运算分量只能是整型或字符型数据,位运算把 ...

  3. STM32 定时器详解

    STM32 定时器详解 吃了一个猛亏,自己理解花了大半天时间,结果一看代码发现巨简单 算了,把自己理解的放上来吧 目录 STM32 定时器详解 前言 一.定时器种类和区分 二.时钟源 三.计数过程 3 ...

  4. STM32 DAC详解

    目录 01.DAC简介 02.DAC转换 03.功能说明 04.DAC输出电压 05.代码配置 上一篇介绍了<STM32ADC详解>,既然有模拟转数字的ADC模块,那么就必然有数字转模拟的 ...

  5. STM32 GPIO 详解

    0. 实验平台 基于STM32F407ZG 1. GPIO 简介 1.1 简介 GPIO全称:General Purpose Input Output,即通用输入输出端口,一般用来采集外部器件的信息或 ...

  6. STM32 SPI详解

    目录 1.SPI简介 2.SPI特点 2.1.SPI控制方式 2.2.SPI传输方式 2.3.SPI数据交换 2.4.SPI传输模式 3.工作机制 3.1.相关缩写 3.2.CPOL极性 3.3.CP ...

  7. 【STM32】ADC详解

    00. 目录 文章目录 00. 目录 01. ADC简介 02. ADC主要特性 03. ADC功能说明 04. ADC开关控制 05. ADC时钟 06. 通道选择 07. 转换模式 08. 时序图 ...

  8. STM32开发 -- ADC详解

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/89498527 最近项目中有用到ADC,正好来做一下总结. 一.ADC简介 A ...

  9. STM32F4_模数转换器(ADC)详解

    目录 1. ADC是什么 2. ADC主要特性 3. ADC框图 3.1 ADC开关控制 3.2 ADC时钟 3.3 通道选择 3.4 单次转换模式和连续转换模式 3.5 时序图 3.6 模拟看门狗 ...

最新文章

  1. ucache来广营(望京)机房
  2. Misc-wireshark-1(秒懂!!)
  3. 罗切斯特大学排名计算机排名,罗切斯特大学排名
  4. 从阿姆斯特丹建设智能交通能得到什么经验?
  5. Redis ,Memcached ,Mongodb 对比
  6. 跳槽到新公司,我直接让项目的性能提升了一半。。。
  7. [MSN谈话]专注、口碑和猎头
  8. 时间复杂度(3):排序算法的时间复杂度 空间复杂度 总结
  9. LFW pairs.txt解释
  10. Remoting整理
  11. 计算机用户密码开机设置,计算机开机密码和屏保密码设置指南
  12. 集合论的ZFC公理系统
  13. lack名词形式_lack是什么意思_lack在线翻译_英语_读音_用法_例句_海词词典
  14. duang,duang!!duang.java.mustReadTips
  15. android 打开微信扫一扫
  16. Jenkins拉取代码返回错误码128
  17. java-使用 flying-saucer 通过 xhtml 生成 pdf 文档支持 css 和 图片
  18. shell 编程arry数组
  19. 热点新闻管理系统设计与实现
  20. idea设置console控制台显示内容大小-小白实操记录

热门文章

  1. 周末时间学习Linux
  2. vostro3070装win7_戴尔Vostro 3660台式机怎么装win7系统
  3. 某客户领导汇报材料编写问题与思考
  4. 【leetcode】43.1~n整数中1出现的次数
  5. heic格式转化jpg,heic转jpg方法
  6. MWC 2019新品汇总:5G+折叠屏开启的新时代?
  7. pdf怎么合并成一个pdf?怎么把几个pdf合并成一个pdf文件?
  8. C语言基础学习Day12(完结篇)
  9. 【毕业设计】自动泊车系统(APS)记录
  10. Qt for python 的属性系统使用,并注册python到qml使用