STM32 的ADC使用指南

ADC简介

ADC,即模数转换器(Analog-to-Digital Converter),是一种在微控制器(如STM32)中常见的设备,它能够将模拟信号转换为数字信号。简单来说,我们的现实世界中大部分的信号都是模拟的,比如声音、光线强度、温度等,它们的变化是连续的。而微控制器是数字设备,它处理的是0和1的数字信号。 ADC让我们可以读取模拟信号的值,然后将这个连续变化的信号转换成一系列数字,微控制器就可以读取这些数字进行进一步的处理了。举个例子,如果你有一个测量温度的传感器,它输出的是电压变化,你可以用ADC读取这些电压变化,然后转换成温度值。 在STM32等微控制器中,ADC的分辨率通常是12位的,这意味着它可以将模拟信号转换为0到4095之间的数字值(2的12次方等于4096个不同的值)。如果ADC是10位的,它就可以输出0到1023之间的值(2的10次方等于1024个不同的值)

ADC可以读取哪些模拟信号?

  1. 电压信号:直接测量通过电阻分压器或其他电压源产生的电压。
  2. 电流信号:通过电流传感器如霍尔效应传感器产生的模拟输出。
  3. 压力信号:使用压力传感器将压力变化转换为电压信号读取。
  4. 光强信号:例如利用光敏电阻或光敏二极管测量环境的光线强度。
  5. 湿度信号:通过湿度传感器,将环境的湿度变化转换为可读的电压信号。
  6. 声音信号:通过麦克风传感器将环境中的声波转换为电压信号。

ADC的分辨率和采样速率有什么关系?

ADC的分辨率和采样速率是两个不同的概念,它们描述了模数转换器的不同特性:

  1. 分辨率:分辨率决定了ADC可以区分的最小电压差值。由ADC的位数决定,位数越高,分辨率越高,能够检测到的最小电压变化就越小。例如,一个12位的ADC具有2^12(4096)个不同的可能的输出值。
  2. 采样速率:采样速率(或采样频率)是ADC单位时间内可以执行的采样次数。它通常以赫兹(Hz)为单位。采样率越高,ADC就能够更频繁地采集数据,更好地跟踪快速变化的信号。

两者之间的关系是,在保持一定的分辨率的条件下,增加采样速率可能需要更强大的ADC性能和更高的处理能力。同时,根据奈奎斯特定理,为了准确地重建一个模拟信号,采样频率需要至少是信号最高频率的两倍。 总的来说,分辨率描述了ADC测量精度的能力,而采样速率描述了ADC测量频率的能力。在实际应用中,两者需要根据具体的测量需求和性能要求来平衡选择。

STM32中ADC的工作原理

在STM32微控制器中,ADC(模数转换器)的工作原理基于将模拟信号(如电压)转化为数字值的过程。以下是ADC在STM32中的基本工作方式:

  1. 采样 - ADC首先对模拟信号进行采样,即在特定的时刻捕获信号的值。STM32的ADC可以配置为手动触发采样或通过定时器等外部事件自动触发。
  2. 保持 - 模拟信号被ADC的采样保持电路捕获并保持在一定时间内,这样便于转换电路准确读取到这个值。保持时间需要足够长,以确保转换的准确性。
  3. 量化 - 模拟信号通过ADC内的量化电路转换成数字值。量化过程是将采样的模拟信号划分到一定数量的离散区间内,并将这个模拟信号转换为代表这个区间的数字值。在STM32的ADC通常可以是12位的,即4096个区间。
  4. 转换 - 量化后的数字信号是模拟信号的近似数字表示。这个数字最终通过ADC寄存器可以被微控制器读取和处理。
  5. 输出 - 微控制器通过读取ADC数据寄存器,获取转换结果。这个结果通常是以二进制或十六进制的格式表示,但可以根据需要,通过软件算法转换成相应的物理单位(比如温度、压力等)。

在STM32中,通过配置ADC寄存器,开发者可以定制化ADC工作方式,例如选择不同的采样时间、分辨率、通道,以及是否启用连续采样或单次采样等。每个STM32系列的微控制器可能有多个ADC模块,并且每个ADC模块可能有多个通道。基于具体的应用需求,开发者可以选择合适的ADC以及相应的配置来进行数据的采集和处理。

重要寄存器

  1. ADC_CommonInitTypeDef:这不是一个单独的寄存器,但它是一个结构体,用于初始化ADC的通用设置,适用于包含多个ADC模块的STM32芯片。
  2. ADC_CR1ADC_CR2(控制寄存器1和2):这些寄存器用于控制ADC的主要功能,如转换分辨率、连续转换模式、触发源选择等。
  3. ADC_SMPR1ADC_SMPR2(采样时间寄存器1和2):这些寄存器用于配置各个ADC通道的采样时间。
  4. ADC_HTRADC_LTR(看门狗高阈值和低阈值寄存器):如果使用模拟看门狗功能,将会用到这些寄存器来设置高低阈值。
  5. ADC_SQR1ADC_SQR2ADC_SQR3(规则序列寄存器):用于设置规则转换序列和每次序列要转换的通道数量。
  6. ADC_JSQR(注入序列寄存器):如果使用注入通道功能,用于设置注入序列和转换的通道。
  7. ADC_DR(数据寄存器):用于读取转换结果的电压值。
  8. ADC_CCR(公共控制寄存器):适用于一些特定的STM32芯片,用于控制与多个ADC模块相关的某些特性,如温度传感器、Vrefint引用电压等。

如何配置这些寄存器

在程序中配置STM32的ADC寄存器,一般需要以下步骤:

  1. 启用ADC和GPIO时钟 :使用RCC_APB2PeriphClockCmd()函数启用ADC和与ADC输入通道相对应的GPIO端口的时钟。

    cpp 复制代码
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOx, ENABLE);
  2. 配置ADC使用的GPIO为模拟输入模式 :将GPIO端口配置为模拟输入模式以用于ADC。

    cpp 复制代码
    GPIO_InitTypeDef GPIO_InitStructure; 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x; // 替换x为实际的引脚 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
    GPIO_Init(GPIOx, &GPIO_InitStructure); // 替换x为实际的端口
  3. 复位并初始化ADC :创建ADC_InitTypeDef结构体并使用ADC_StructInit()函数进行初始化。

    cpp 复制代码
    ADC_InitTypeDef ADC_InitStructure; ADC_StructInit(&ADC_InitStructure);
  4. 配置特定于ADC的寄存器

    • 使用ADC_Init()函数配置ADC_CR1和ADC_CR2。

    • 根据ADC通道数配置ADC_SMPR1和ADC_SMPR2。

    • 设定ADC转换序列与转换次数(ADC_SQR1, ADC_SQR2和ADC_SQR3)。

      cpp 复制代码
      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
      ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 或 ENABLE,取决于是单通道还是多通道 
      
      ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 或 DISABLE 
      
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
      ADC_InitStructure.ADC_NbrOfChannel = 1; // 根据需要设置通道数
      
      ADC_Init(ADC1,&ADC_InitStructure); 
      ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 1, ADC_SampleTime_55Cycles5); // x是通道号
  5. 校准并启用ADC :在诸如ADC_CR2这样的寄存器中启用ADC然后启动校准过程。

    cpp 复制代码
    ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); 
    
    while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); 
    
    while(ADC_GetCalibrationStatus(ADC1));
  6. 启动ADC转换 :软件启动ADC或配置触发器自动启动转换。

    cpp 复制代码
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  7. 读取ADC值 :从ADC_DR寄存器读取转换结果。

    cpp 复制代码
    uint16_t ADC_Value = ADC_GetConversionValue(ADC1);

请根据具体的STM32型号和库函数版本查看参考手册和标准外设库,因为不同的型号和库函数版本有一些差异。这些设置应作为指导,应根据你实际使用的STM32系列进行调整。

完整示例代码

cpp 复制代码
#include "stm32f10x.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
void ADC1_Init(void) {
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    // 1. 使能ADC1和GPIO端口时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
    // 2. 配置PC.04 作为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    // 3. ADC结构体初始化
    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;
    ADC_Init(ADC1, &ADC_InitStructure);
    // 4. 配置ADC1的通道11为顺序进行规则转换的第一个转换
    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5);
    // 5. 使能 ADC1
    ADC_Cmd(ADC1, ENABLE);
    // 6. 初始化ADC1的校准寄存器,并开始校准
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    // 7. 开始转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
int main(void) {
    // 初始化ADC
    ADC1_Init();
    while (1) {
        // 检测转换结束
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
        // 读取ADC转换结果
        uint16_t ADC_Value = ADC_GetConversionValue(ADC1);
        // ... 使用ADC_Value进行其他操作
    }
}

这份代码是非常基础的STM32使用ADC的例子,使用标准外设库函数进行简单的ADC配置和读取。步骤如下:

  1. 使能GPIO和ADC时钟。
  2. 设置ADC使用的GPIO口为模拟输入模式。
  3. 对ADC进行基础配置,如工作模式,数据对齐方式等。
  4. 设置ADC通道,这里以通道14为例。
  5. 使能ADC并校准。
  6. 开始ADC转换。
相关推荐
Wallace Zhang10 分钟前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭14 分钟前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
HX科技9 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Suagrhaha9 天前
驱动入门的进一步深入
linux·嵌入式硬件·驱动
国科安芯10 天前
基于ASP4644多通道降压技术在电力监测系统中集成应用与发展前景
嵌入式硬件·硬件架构·硬件工程
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
进击的程序汪10 天前
触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报
linux·网络·嵌入式硬件