STM32——ADC

STM32——ADC

宗旨:技术的学习是有限的,分享的精神的无限的。

一、ADC指标

有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行 ;ADC的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中 ;模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高 / 低阈值。

对于 ADC 来说,我们最关注的就是它的分辨率、转换时间、ADC 类型、参考电压范围:

(1)分辨率:12 位分辨率。不能直接测量负电压,所以没有符号位,即其最小量化单位 LSB= Vref+ / 212

(2)转换时间:转换时间是可编程的。采样一次至少要用 14 个 ADC 时钟周期,而 ADC 的时钟频率最高为 14MHz,也就是说,它的采样时间最短为 1us。足以胜任中、低频数字示波器的采样工作。

(3)ADC类型:STM32 的是逐次比较型 ADC。

(4)参考电压

STM32的 ADC 是不能直接测量负电压的,而且其输入的电压信号的范围为 :V REF- ≤ V IN ≤ V REF+。当需要测量负电压或测量的电压信号超出范围时,要先经过运算电路进行平移或利用电阻分压。

二、ADC工作过程

输入信号经过这些通道被送到 ADC 部件,ADC 部件需要受到触发信号才开始进行转换,如 EXTI 外部触发、定时器触发,也可以使用软件触发。ADC 部件接收到触发信号之后,在 ADCCLK 时钟的驱动下对输入通道的信号进行采样,并进行模数转换,其中ADCCLK 是来自 ADC 预分频器的。

ADC 部件转换后的数值被保存到一个 16 位的规则通道数据寄存器(或注入通道数据寄存器)之中,我们可以通过 CPU 指令或 DMA 把它读取到内存(变量)。模数转换之后,可以触发 DMA 请求或者触发 ADC 的转换结束事件。如果配置了模拟看门狗,并且采集得的电压大于阈值,会触发看门狗中断。

三、ADC采集数据【DMA模式】

在 STM32 中,使用 ADC 时往往采用 DMA 传输方式,由 DMA 把 ADC 外设转换的数据传输到 SRAM,再进行处理,甚至直接把 ADC 的数据转移到串口发送给上位机。【中断效率还是不够】

1、配置GPIO端口

配置完成 ADC 及 DMA 后,ADC 就不停地采集数据,而 DMA自动地把 ADC 采集的数据转移至内存中的变量 ADC_ConvertedValue 中,所以在 main 函数的 while 循环中使用的 ADC_ConvertedValue都是实时值。

/*
使能 DMA 时钟、GPIO 时钟及 ADC1 时钟。然后把 ADC1 的通道 11 使用的 GPIO 引脚 PC1 配置成模拟输入模式,在作为 ADC 的
输入时,必须使用模拟输入。每个 ADC 通道都对应一个 GPIO 引脚端口,GPIO 的引脚在设置为模拟输入模式后可用于模拟电压的输入。
*/
static void ADC1_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* 使能DMA时钟 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); /* 使能ADC和GPIOC时钟 */

  /* 配置PC1位模拟输入,输入模式不用设置速率 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

2、配置DMA和ADC模式

typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;

typedef struct
{
  uint32_t ADC_Mode;
  FunctionalState ADC_ScanConvMode;
  FunctionalState ADC_ContinuousConvMode;
  uint32_t ADC_ExternalTrigConv;
  uint32_t ADC_DataAlign;
  uint8_t ADC_NbrOfChannel;
} ADC_InitTypeDef;

(1)ADC_Mode:用于测量电阻分压后的电压值,要求不高,只使用一个 ADC 就可以满足要求了,所以本成员被赋值为 ADC_Mode_Independent
(独立模式)。

(2)ADC_ScanConvMode:当有多个通道需要采集信号时,可以把 ADC 配置为按一定的顺序来对各个通道进行扫描转换,即轮流采集各通道的值。

(3)ADC_ContinuousConvMode:连续转换模式,此模式与单次转换模式相反,单次转换模式 ADC 只采集一次数据就停止转换。而连续转换模式则在上一次
ADC 转换完成后,立即开启下一次转换。

(4)ADC_ExternalTrigConv:ADC 需要在接收到触发信号后才开始进行模数转换,如外部中断触发(EXTI
线)、定时器触发,这两个为外部触发信号,如果不使用外部触发信号可以使用软件控制触发 。

(5)ADC_DataAlign:数据对齐方式。

(6)ADC_NbrOfChannel:这个成员保存了要进行 ADC 数据转换的通道数,可以为1 ~ 16 个。

填充完结构体,就可以调用外设初始化函数进行初始化了,ADC 的初始化使用ADC_Init() 函数,初始化完成后别忘记调用 ADC_Cmd() 函数来使能 ADC 外设,用ADC_DMACmd() 函数来使能 ADC 的 DMA 接口。

/*
ADC 的 DMA 配 置 部 分 与 串 口 DMA 配 置 部 分 类 似, 它 的 DMA 整 体 上 被 配置 为 : 使 用 DMA1 的 通 道 1 , 数 据 从 ADC 外 设 的 数 据 寄 存 器
(ADC1_DR_Address) 转 移 到 内 存(ADC_ConvertedValue 变量),内存、外设地址都固定,每次传输的数据大小为半字(16 位),使用 DMA 循环传输模式。
*/
static void ADC1_Mode_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;

  DMA_DeInit(DMA1_Channel1); /* DMA通道1 */

  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC 地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //内存地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  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_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  DMA_Cmd(DMA1_Channel1, ENABLE); /* 使能DMA通道1 */

  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立 ADC 模式
  ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止扫描模式,扫描模式用于多通道采集
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式,即不停地进行 ADC 转换
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
  ADC_InitStructure.ADC_NbrOfChannel = 1; //要转换的通道数目 1
  ADC_Init(ADC1, &ADC_InitStructure);

  RCC_ADCCLKConfig(RCC_PCLK2_Div8);  /*配置 ADC 时钟,为 PCLK2 的 8 分频,即 9MHz*/
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1,  ADC_SampleTime_55Cycles5);  /*配置 ADC1 的通道 11 为 55. 5 个采样周期,序列为 1 */

  ADC_DMACmd(ADC1, ENABLE); /* 使能ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  ADC_ResetCalibration(ADC1);  /*复位校准寄存器 */
  while(ADC_GetResetCalibrationStatus(ADC1));  /*等待校准寄存器复位完成 */

  ADC_StartCalibration(ADC1);  /* ADC 校准 */
  while(ADC_GetCalibrationStatus(ADC1));  /* 等待校准完成*/

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);  /*  由于没有采用外部触发,所以使用软件触发 ADC 转换  */
}

3、ADC转换时间

PCLK2 的常用时钟频率为 72 MHz,而 ADCCLK 必须低于 14 MHz,所以在这个情况下,ADCCLK 最 高 频 率 为 PCLK2 的 8 分 频, 即 ADCCLK=9 MHz。 若 希 望 使 ADC以 最 高 频 率 14 MHz 运行,可以把 PCLK2配置为 56 MHz,然后再 4 分频得到ADCCLK。

ADC 的转换时间不仅与 ADC 的时钟有关,还与采样周期相关。每个不同的 ADC 通道都可以设置为不同的采样周期。

4、ADC自校准

开始 ADC 转换之前,需要启动 ADC 的自校准。ADC 有一个内置自校准模式,校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。

5、计算电压值

实际电压值 = ADC转换值 ×LSB;STM32 的 ADC 的精度为 12 位,而中 V REF+ 接的参考电压值为 3.3V ,所以 LSB =3.3/212

时间: 2024-10-21 04:04:49

STM32——ADC的相关文章

STM32 ADC 测电压

1. STM32F103 ADC 本例使用STM32F103芯片的PA1引脚测试模拟输入的电压值. 查看文档<STM32F103X.pdf>第31页,引脚定义图: 得知PA1使用ADC1的通道1. 查看文档<STM32F103X.pdf>第13页,时钟树图: 得知ADC1可2,4,6,8分频,又ADC输入时钟不得超过14MHZ(参见STM32参考手册RM0008第11章ADC). //初始化ADC //这里我们仅以规则通道为例 //我们默认将开启通道0~3 void Adc_Ini

STM32.ADC

ADC实验 原理图: 1.ADC配置函数 /* enable adc1 and config adc1 to dma mode */ ADC1_Init(); /** * @brief ADC1初始化 * @param 无 * @retval 无 */ void ADC1_Init(void) { ADC1_GPIO_Config(); //端口初始化 ADC1_Mode_Config(); } 对于配置ADC1的工作模式为MDA模式 ADC1是挂载到DMA1的通道1的 #define ADC1

stm32 adc计算

用STM32自带的ADC读取引脚电压值,读回来的数据怎么转换成单位为V的数值??? V(ADC) = Value(ADC) * V(ref)/4096 (stm32的ADC是12位的,所以ad字的最大值是4096) 其中V(ADC)为算出的电压值:Value(ADC)为采集的AD值:V(ref)为参考电压,一般为3.3V. 比如你STM32的参考电压为3.3v,采集的AD值为1024,那么转换为电压V(ADC) = 1024×3.3/4096 = 0.825V

STM32 ADC基础与多通道采样

12位ADC是一种逐次逼近型模拟数字数字转换器.它有多达18个通道,可测量16个外部和2个内部信号源.ADC的输入时钟不得超过14MHZ,它是由PCLK2经分频产生.如果被ADC转换的模拟电压低于低阀值或高于高阀值,AWD模拟看门狗状态位被设置. ADC通常要与DMA一起使用 这里只是简单的用库配置ADC 不断扫描来实现ADC的应用. 配置DMA: void DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体 DM

对STM32 ADC单次转换模式 连续转换模式 扫描模式的理解

举例 用ADC1 规则通道的顺序为CH0,CH1,CH2,CH3, 不启动SCAN模式: 在单次转换模式下: 启动ADC1,则 1.开始转换CH1(ADC_SQR的第一通道) 转换完成后停止,等待ADC的下一次启动,继续从第一步开始转换 在连续转换模式下: 启动ADC1,则 1.开始转换CH0(ADC_SQR的第一通道) 转换完成后回到第一步,继续转换 启动SCAN模式下 在单次转换模式下: 启动ADC1,则 1.开始转换CH0. 2.转换完成后自动开始转换CH1 3.转换完成后自动开始转换CH

STM32 ADC DMA 中断模式多通道读取ADC转换值

因为做一个电机控制项目,其中需要用到用PWM触发ADC,读取ADC的转换值. 这里有两个关键问题: 第一,如何使PWM触发ADC转换? 第二,如何在ADC多通道扫描模式下,读取各个channel的adc转换值? 第三,如何使用DMA读取多通道ADC转换值? 第一个问题,首先需要将ADC设置成外部触发转换,第二需要选择触发是发生在Timer的上升沿还是下降沿.程序如下: adc.ADC_Resolution = ADC_Resolution_12b; adc.ADC_ScanConvMode =E

STM32 ADC规则组和注入组配置方法

//############################################################//近期在用STM32F103编写无刷电机矢量控制,在配置ADC模式时遇到很多奇怪的问题,网上能说清楚的资料太少,//公布我配置的结果,实测OK//3组规则通道连续转换+DMA//2组注入通道TIM1的4通道触发(规格书未说明是上升沿还是下降沿触发,实测波形为上升沿触发)//##################################################

stm32之TIM+ADC+DMA采集50HZ交流信号

http://cache.baiducontent.com/c?m=9d78d513d98207f04fece47f0d01d7174a02d1743ca6c76409c3e03984145b563710f4bb56644b5bc7823c390ef50f1aa8e737012a1e65f2dedf883d80f9c57478de6323706bd71c4dce5ff58b11769737902cefaa18ecb9e732e5adc5d3a95744ca245f3cdfae&p=8b2a975

STM32学习笔记1(ADC多通道采样)

STM32 ADC多通道转换描述:用ADC连续采集11路模拟信号,并由DMA传输到内存.ADC配置为扫描并且连续转换模式,ADC的时钟配置为12MHZ.在每次转换结束后,由DMA循环将转换的数据传输到内存中.ADC可以连续采集N次求平均值.最后通过串口传输出最后转换的结果.程序如下:#i nclude "stm32f10x.h" //这个头文件包括STM32F10x所有外围寄存器.位.内存映射的定义#i nclude "eval.h" //头文件(包括串口.按键.L