stm32配置ADC模数转换

我们以STM32F1系列为例,使用标准库函数来配置ADC。ADC(模数转换器)将模拟信号转换为数字信号。STM32的ADC是12位逐次逼近型ADC。以下我们简要介绍ADC的工作原理和配置步骤。

ADC工作原理简述:
采样保持:ADC对输入电压进行采样并保持,以便进行转换。

逐次逼近:ADC使用逐次逼近寄存器(SAR)从最高位(MSB)开始依次确定每一位的值,最终得到12位的数字量。

转换结束:转换完成后,将结果存储在数据寄存器中,并可以产生中断。

STM32 ADC相关寄存器(部分):
ADC_CR1和ADC_CR2:控制寄存器,用于配置ADC的工作模式、扫描模式、连续转换、外部触发等。

ADC_SMPR1和ADC_SMPR2:采样时间寄存器,用于配置各通道的采样时间。

ADC_SQR1~3:规则序列寄存器,用于配置规则转换的通道序列。

ADC_DR:数据寄存器,存储转换结果。

ADC_SR:状态寄存器,包含转换状态标志(如EOC-转换结束标志)。

程序框架设计:
初始化ADC用到的GPIO:将模拟输入通道对应的GPIO配置为模拟输入模式。

初始化ADC:设置ADC的工作模式、数据对齐、扫描模式、连续转换模式、触发方式、分辨率等。

配置ADC通道:设置采样时间,以及通道在转换序列中的顺序。

使能ADC:启动ADC,开始转换。

读取转换结果:可以通过轮询或中断的方式读取ADC_DR中的值。

代码示例(基于标准库):
下面是一个简单的ADC配置代码,用于单通道连续转换,并通过轮询方式读取转换值。我们在注释中说明每一步对应的寄存器操作及其作用。

c

include "stm32f10x.h"

void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;

// 1. 初始化ADC用到的GPIO: PA0 作为模拟输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 2. 初始化ADC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 使能ADC1时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 设置ADC分频因子6,即12MHz(假设系统时钟72MHz)

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道,非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换
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);

// 3. 配置ADC通道:规则序列,采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 通道0,序列1,采样时间55.5周期

// 4. 使能ADC
ADC_Cmd(ADC1, ENABLE); // 使能ADC1

// 5. 校准ADC(可选,但推荐)
ADC_ResetCalibration(ADC1); // 重置校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1)); // 等待重置校准完成
ADC_StartCalibration(ADC1); // 开始校准
while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成

// 6. 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件启动转换

}

// 读取ADC值
uint16_t ADC_GetValue(void)
{
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换结束
return ADC_GetConversionValue(ADC1); // 返回转换结果
}
寄存器操作对应说明:
GPIO初始化:配置GPIO为模拟输入,实际上是将GPIO的配置寄存器(如GPIOx_CRL和GPIOx_CRH)设置为模拟输入模式,同时断开上下拉。这样GPIO引脚直接连接到ADC的输入。

ADC初始化:

RCC_ADCCLKConfig(RCC_PCLK2_Div6):设置ADC时钟分频,对应RCC寄存器中的相应位(RCC_CFGR的ADCPRE位),将APB2时钟(PCLK2)分频,得到ADC时钟(最大14MHz)。

ADC_Init()函数配置多个控制寄存器(ADC_CR1和ADC_CR2):

ADC_Mode:设置ADC_CR1的DUALMOD位,这里为独立模式,即这些位为0。

ADC_ScanConvMode:对应ADC_CR1的SCAN位,用于扫描模式,这里禁用。

ADC_ContinuousConvMode:对应ADC_CR2的CONT位,连续转换模式。

ADC_ExternalTrigConv:对应ADC_CR2的EXTSEL位,选择软件触发,即这些位为0,并且使用软件触发(ADC_CR2的SWSTART位或EXTTRIG位)。

ADC_DataAlign:对应ADC_CR2的ALIGN位,数据对齐方式,这里为右对齐(0)。

ADC_NbrOfChannel:这个参数在配置序列寄存器时使用,这里为1。

ADC通道配置:

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5):

选择通道0(ADC_Channel_0)在规则序列中的第一个位置(1),对应规则序列寄存器ADC_SQR3的SQ1位(因为只有一个转换,所以放在第一个)。

设置采样时间为55.5周期,对应ADC_SMPR2寄存器中通道0的采样时间设置(SMP0位)。

使能ADC:

ADC_Cmd(ADC1, ENABLE):设置ADC_CR2的ADON位为1,使能ADC。

ADC校准:

ADC_ResetCalibration和ADC_StartCalibration:操作ADC_CR2的RSTCAL和CAL位,进行校准。校准可以减小转换误差。

启动转换:

ADC_SoftwareStartConvCmd(ADC1, ENABLE):设置ADC_CR2的SWSTART位,启动转换。

读取转换值:

等待ADC_SR的EOC位(转换结束标志)为1,然后读取ADC_DR寄存器的值。

对应工作原理的步骤:
采样保持:通过配置采样时间(ADC_SMPR2)来控制采样周期,采样时间越长,采样越准确。

逐次逼近:由ADC硬件自动完成,我们只需要启动转换。

转换结束:通过检查EOC标志位来判断转换是否完成,然后读取数据寄存器ADC_DR。

这样,我们就完成了ADC的配置和读取。请注意,不同系列的STM32可能有不同的寄存器配置,但基本原理相似。以上代码和解释基于STM32F1系列。

ADC参数配置:

分辨率:设为12位、10位、8位或6位。12位最常用,精度最高。

对齐方式:左对齐还是右对齐。通常用右对齐,这样读取到的值就是一个从0到最大值的自然数。

扫描/单次模式:是连续转换还是只转换一次。

连续/单次模式:在单次模式下,转换一次就停止;在连续模式下,转换完会自动开始下一次。

触发源选择:选择是软件触发还是具体的哪个硬件定时器触发。

posted @ 2025-10-15 16:23  质荷  阅读(38)  评论(0)    收藏  举报