STM32_ADC_寄存器操作

文章目录

  • 一、ADC寄存器
    • [   1、ADC状态寄存器(ADC_SR)](#   1、ADC状态寄存器(ADC_SR))
    • [   2、ADC控制寄存器 1(ADC_CR1)](#   2、ADC控制寄存器 1(ADC_CR1))
    • [   3、ADC控制寄存器 2(ADC_CR2)](#   3、ADC控制寄存器 2(ADC_CR2))
    • [   4、ADC采样时间寄存器 1(ADC_SMPR1)](#   4、ADC采样时间寄存器 1(ADC_SMPR1))
    • [   5、ADC采样时间寄存器 2(ADC_SMPR2)](#   5、ADC采样时间寄存器 2(ADC_SMPR2))
    • [   6、ADC注入通道数据偏移寄存器x (ADC_JOFRx)(x=1..4)](#   6、ADC注入通道数据偏移寄存器x (ADC_JOFRx)(x=1..4))
    • [   7、ADC看门狗高阀值寄存器(ADC_HTR)](#   7、ADC看门狗高阀值寄存器(ADC_HTR))
    • [   8、ADC看门狗低阀值寄存器(ADC_LRT)](#   8、ADC看门狗低阀值寄存器(ADC_LRT))
    • [   9、ADC规则序列寄存器 1(ADC_SQR1)](#   9、ADC规则序列寄存器 1(ADC_SQR1))
    • [   10、ADC规则序列寄存器 2(ADC_SQR2)](#   10、ADC规则序列寄存器 2(ADC_SQR2))
    • [   11、ADC规则序列寄存器 3(ADC_SQR3)](#   11、ADC规则序列寄存器 3(ADC_SQR3))
    • [   12、ADC注入序列寄存器(ADC_JSQR)](#   12、ADC注入序列寄存器(ADC_JSQR))
    • [   13、ADC 注入数据寄存器x (ADC_JDRx) (x= 1..4)](#   13、ADC 注入数据寄存器x (ADC_JDRx) (x= 1..4))
    • [   14、ADC规则数据寄存器(ADC_DR)](#   14、ADC规则数据寄存器(ADC_DR))
    • [   15、ADC寄存器地址映像](#   15、ADC寄存器地址映像)
  • 二、代码实例
    • [   1、ADC1 单次采样(PA0,查询模式)](#   1、ADC1 单次采样(PA0,查询模式))
    • [   2、ADC1 连续采样(PA0,中断模式)](#   2、ADC1 连续采样(PA0,中断模式))
    • [   3、ADC1 多通道扫描(PA0/CH0 + PA1/CH1,DMA 批量采集)](#   3、ADC1 多通道扫描(PA0/CH0 + PA1/CH1,DMA 批量采集))
  • 三、总结
    • [   1、核心寄存器](#   1、核心寄存器)
    • [   2、注意事项](#   2、注意事项)
    • [   3、ADC 寄存器编程核心流程:](#   3、ADC 寄存器编程核心流程:)

一、ADC寄存器

   1、ADC状态寄存器(ADC_SR)

     地址偏移:0x00

     复位值:0x0000 0000

    

   2、ADC控制寄存器 1(ADC_CR1)

     地址偏移:0x04

     复位值:0x0000 0000

    

    

   3、ADC控制寄存器 2(ADC_CR2)

     地址偏移:0x08

     复位值:0x0000 0000

    

    

    

   4、ADC采样时间寄存器 1(ADC_SMPR1)

     地址偏移:0x0C

     复位值:0x0000 0000

    

   5、ADC采样时间寄存器 2(ADC_SMPR2)

     地址偏移:0x10

     复位值:0x0000 0000

    

   6、ADC注入通道数据偏移寄存器x (ADC_JOFRx)(x=1...4)

     地址偏移:0x14-0x20

     复位值:0x0000 0000

    

   7、ADC看门狗高阀值寄存器(ADC_HTR)

     地址偏移:0x24

     复位值:0x0000 0000

    

   8、ADC看门狗低阀值寄存器(ADC_LRT)

     地址偏移:0x28

     复位值:0x0000 0000

    

   9、ADC规则序列寄存器 1(ADC_SQR1)

     地址偏移:0x2C

     复位值:0x0000 0000

    

   10、ADC规则序列寄存器 2(ADC_SQR2)

     地址偏移:0x30

     复位值:0x0000 0000

    

   11、ADC规则序列寄存器 3(ADC_SQR3)

     地址偏移:0x34

     复位值:0x0000 0000

    

   12、ADC注入序列寄存器(ADC_JSQR)

     地址偏移:0x38

     复位值:0x0000 0000

    

   13、ADC 注入数据寄存器x (ADC_JDRx) (x= 1...4)

     地址偏移:0x3C -- 0x48

     复位值:0x0000 0000

    

   14、ADC规则数据寄存器(ADC_DR)

     地址偏移:0x4C

     复位值:0x0000 0000

    

   15、ADC寄存器地址映像

    

    

二、代码实例

   1、ADC1 单次采样(PA0,查询模式)

     最基础的 ADC 用法,单次触发转换、查询结果,适合低频采样场景。

c 复制代码
		#include "stm32f10x.h"
		
		/**
		 * @brief  系统时钟初始化(72MHz,HSE=8MHz)
		 */
		void SystemClock_Init(void)
		{
		    RCC->CR |= RCC_CR_HSEON;
		    while(!(RCC->CR & RCC_CR_HSERDY));
		    
		    FLASH->ACR |= FLASH_ACR_LATENCY_2;
		    RCC->CFGR &= ~RCC_CFGR_HPRE;
		    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
		    RCC->CFGR &= ~RCC_CFGR_PPRE2;
		    
		    RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL);
		    RCC->CFGR |= RCC_CFGR_PLLMULL9;
		    
		    RCC->CR |= RCC_CR_PLLON;
		    while(!(RCC->CR & RCC_CR_PLLRDY));
		    
		    RCC->CFGR &= ~RCC_CFGR_SW;
		    RCC->CFGR |= RCC_CFGR_SW_PLL;
		    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
		}
		
		/**
		 * @brief  ADC1初始化(单次转换,CH0/PA0,查询模式)
		 */
		void ADC1_Single_Init(void)
		{
		    // 1. 开启时钟:GPIOA、ADC1
		    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN;
		    // ADC时钟分频:6分频(72/6=12MHz ≤14MHz)
		    RCC->CFGR &= ~RCC_CFGR_ADCPRE;
		    RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;
		
		    // 2. 配置GPIO:PA0模拟输入(无上下拉)
		    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0); // 模拟输入模式
		
		    // 3. 配置ADC1核心参数
		    ADC1->CR1 &= ~ADC_CR1_SCAN; // 关闭扫描模式(单次通道)
		    ADC1->CR2 &= ~ADC_CR2_CONT; // 关闭连续转换(单次转换)
		    ADC1->CR2 &= ~ADC_CR2_ALIGN; // 数据右对齐(低12位有效)
		    ADC1->SQR1 &= ~ADC_SQR1_L;  // 转换序列长度:1(L[3:0]=0000)
		    ADC1->SQR3 &= ~ADC_SQR3_SQ1; // 转换序列第1位:CH0(0)
		    ADC1->SQR3 |= 0;
		
		    // 4. 配置采样时间:CH0采样时间239.5周期(提高精度)
		    ADC1->SMPR2 &= ~ADC_SMPR2_SMP0;
		    ADC1->SMPR2 |= ADC_SMPR2_SMP0_2; // SMP0[2:0]=110 → 239.5周期
		
		    // 5. 开启ADC1并校准
		    ADC1->CR2 |= ADC_CR2_ADON;   // 开启ADC
		    ADC1->CR2 |= ADC_CR2_CAL;    // 启动校准
		    while(ADC1->CR2 & ADC_CR2_CAL); // 等待校准完成
		}
		
		/**
		 * @brief  ADC1单次采样(查询模式)
		 * @return 采样值(0~4095)
		 */
		uint16_t ADC1_Single_Read(void)
		{
		    // 1. 启动ADC转换
		    ADC1->CR2 |= ADC_CR2_SWSTART;
		    // 2. 等待转换完成(EOC=1)
		    while(!(ADC1->SR & ADC_SR_EOC));
		    // 3. 读取采样值(DR寄存器,右对齐)
		    return ADC1->DR;
		}
		
		/**
		 * @brief  采样值转电压(mV)
		 * @param  adc_val:ADC采样值(0~4095)
		 * @return 电压值(mV,如1650=1.65V)
		 */
		uint16_t ADC_To_Voltage(uint16_t adc_val)
		{
		    // 公式:电压 = (adc_val / 4095) * 3300mV
		    return (uint32_t)adc_val * 3300 / 4095;
		}
		
		// 主函数
		int main(void)
		{
		    uint16_t adc_val, voltage;
		    
		    SystemClock_Init();
		    ADC1_Single_Init();
		    
		    while(1)
		    {
		        // 单次采样
		        adc_val = ADC1_Single_Read();
		        voltage = ADC_To_Voltage(adc_val);
		        
		        // 可通过串口输出adc_val和voltage,或做其他处理
		        // 简单延时
		        for(uint32_t i=0; i<1000000; i++);
		    }
		}

   2、ADC1 连续采样(PA0,中断模式)

     连续转换 + 中断通知,CPU 无需轮询,适合高频采样场景。

c 复制代码
		#include "stm32f10x.h"
		
		// 全局变量:存储最新采样值
		uint16_t ADC1_Cont_Value = 0;
		
		/**
		 * @brief  ADC1初始化(连续转换,CH0/PA0,中断模式)
		 */
		void ADC1_Cont_IRQ_Init(void)
		{
		    // 1. 时钟/GPIO配置(同场景1)
		    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN;
		    RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;
		    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
		
		    // 2. 配置ADC1:连续转换+中断
		    ADC1->CR1 &= ~ADC_CR1_SCAN;
		    ADC1->CR2 |= ADC_CR2_CONT; // 开启连续转换
		    ADC1->CR2 &= ~ADC_CR2_ALIGN;
		    ADC1->SQR1 &= ~ADC_SQR1_L;
		    ADC1->SQR3 |= 0;
		    ADC1->SMPR2 |= ADC_SMPR2_SMP0_2;
		
		    // 3. 开启ADC转换完成中断
		    ADC1->CR1 |= ADC_CR1_EOCIE; // 开启EOC中断
		    // 4. 配置NVIC(ADC1_IRQn=18号中断)
		    SCB->AIRCR = 0x05FA0800; // 优先级分组2
		    NVIC->IP[18] &= ~0xFF;
		    NVIC->IP[18] |= 0x10;    // 抢占优先级1
		    NVIC->ISER[0] |= (1 << 18); // 使能ADC1中断
		
		    // 5. 开启ADC并校准,启动转换
		    ADC1->CR2 |= ADC_CR2_ADON;
		    ADC1->CR2 |= ADC_CR2_CAL;
		    while(ADC1->CR2 & ADC_CR2_CAL);
		    ADC1->CR2 |= ADC_CR2_SWSTART; // 启动连续转换
		}
		
		/**
		 * @brief  ADC1中断服务函数
		 */
		void ADC1_IRQHandler(void)
		{
		    // 检查转换完成标志
		    if(ADC1->SR & ADC_SR_EOC)
		    {
		        ADC1_Cont_Value = ADC1->DR; // 读取采样值
		        ADC1->SR &= ~ADC_SR_EOC;    // 清除EOC标志
		    }
		}
		
		// 主函数
		int main(void)
		{
		    uint16_t voltage;
		    
		    SystemClock_Init();
		    ADC1_Cont_IRQ_Init();
		    
		    while(1)
		    {
		        // 实时读取连续采样值并转电压
		        voltage = ADC_To_Voltage(ADC1_Cont_Value);
		        // 业务处理逻辑
		    }
		}

   3、ADC1 多通道扫描(PA0/CH0 + PA1/CH1,DMA 批量采集)

     扫描多个通道 + DMA 批量传输,适合多模拟量同步采集(如温度、电压、电流)。

c 复制代码
		#include "stm32f10x.h"
		
		// DMA采集缓冲区:存储CH0和CH1的采样值
		uint16_t ADC1_Scan_Buf[2] = {0};
		#define ADC_SCAN_CH_NUM 2
		
		/**
		 * @brief  ADC1+DMA初始化(多通道扫描,CH0+CH1,DMA1_Channel1)
		 */
		void ADC1_Scan_DMA_Init(void)
		{
		    // 1. 开启时钟:GPIOA、ADC1、DMA1
		    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN;
		    RCC->AHBENR |= RCC_AHBENR_DMA1EN;
		    RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;
		
		    // 2. 配置GPIO:PA0/PA1模拟输入
		    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 | GPIO_CRL_MODE1 | GPIO_CRL_CNF1);
		
		    // 3. 配置ADC1:扫描模式+连续转换
		    ADC1->CR1 |= ADC_CR1_SCAN; // 开启扫描模式
		    ADC1->CR2 |= ADC_CR2_CONT; // 连续转换
		    ADC1->CR2 |= ADC_CR2_DMA;  // 开启ADC DMA模式
		    ADC1->CR2 &= ~ADC_CR2_ALIGN;
		    // 转换序列长度:2(L[3:0]=0001 → 2个通道)
		    ADC1->SQR1 &= ~ADC_SQR1_L;
		    ADC1->SQR1 |= (ADC_SCAN_CH_NUM - 1) << 20;
		    // 转换序列:第1位=CH0,第2位=CH1
		    ADC1->SQR3 &= ~(ADC_SQR3_SQ1 | ADC_SQR3_SQ2);
		    ADC1->SQR3 |= 0 << 0;  // SQ1=CH0
		    ADC1->SQR3 |= 1 << 5;  // SQ2=CH1
		    // 采样时间:CH0/CH1均为239.5周期
		    ADC1->SMPR2 |= ADC_SMPR2_SMP0_2 | ADC_SMPR2_SMP1_2;
		
		    // 4. 配置DMA1_Channel1(ADC1映射通道)
		    DMA1_Channel1->CCR &= ~DMA_CCR_EN; // 关闭DMA通道
		    DMA1_Channel1->CCR = 0;
		    DMA1_Channel1->CCR &= ~DMA_CCR_DIR; // 方向:外设→内存
		    DMA1_Channel1->CCR |= DMA_CCR_MINC; // 内存地址自增
		    DMA1_Channel1->CCR &= ~DMA_CCR_PINC; // 外设地址不自增
		    DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0; // 外设数据宽度:16位
		    DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0; // 内存数据宽度:16位
		    DMA1_Channel1->CCR |= DMA_CCR_CIRC;    // 循环模式(连续采集)
		    DMA1_Channel1->CCR |= DMA_CCR_PL_1;    // 优先级:高
		
		    // 5. 配置DMA地址和长度
		    DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; // 外设地址(ADC_DR)
		    DMA1_Channel1->CMAR = (uint32_t)ADC1_Scan_Buf; // 内存缓冲区
		    DMA1_Channel1->CNDTR = ADC_SCAN_CH_NUM; // 传输长度
		
		    // 6. 启动DMA和ADC
		    DMA1_Channel1->CCR |= DMA_CCR_EN; // 开启DMA
		    ADC1->CR2 |= ADC_CR2_ADON;        // 开启ADC
		    ADC1->CR2 |= ADC_CR2_CAL;         // 校准
		    while(ADC1->CR2 & ADC_CR2_CAL);
		    ADC1->CR2 |= ADC_CR2_SWSTART;     // 启动连续转换
		}
		
		// 主函数
		int main(void)
		{
		    uint16_t voltage0, voltage1;
		    
		    SystemClock_Init();
		    ADC1_Scan_DMA_Init();
		    
		    while(1)
		    {
		        // ADC1_Scan_Buf[0] = CH0采样值,ADC1_Scan_Buf[1] = CH1采样值
		        voltage0 = ADC_To_Voltage(ADC1_Scan_Buf[0]);
		        voltage1 = ADC_To_Voltage(ADC1_Scan_Buf[1]);
		        // 多通道数据处理逻辑
		    }
		}

三、总结

   1、核心寄存器

    

   2、注意事项

     DC 时钟限制

       STM32F103 ADC 时钟最大 14MHz,72MHz 系统时钟下必须 6 分频(72/6=12MHz),否则 ADC 采样精度下降。

     采样时间选择:

       采样时间越长,抗干扰能力越强,常用 239.5 周期(高精度)、13.5 周期(高速);

       公式:采样时间 = (SMPx + 1) × ADC 时钟周期(如 239.5 周期 @12MHz = ~20μs)。

     校准操作:

       每次开启 ADC 后必须执行校准(ADC_CR2_CAL),校准完成后才能启动转换,否则采样值偏差大。

     DMA 循环模式:

       多通道连续采集时,DMA 需开启CIRC循环模式,否则采集完一次后停止。

     电压转换精度:

       公式(adc_val * 3300) / 4095中,需用uint32_t强制转换,避免 16 位整数溢出。

   3、ADC 寄存器编程核心流程:

     开时钟→配 GPIO→配 ADC 参数(扫描 / 连续 / 采样时间)→校准→启动转换→读数据;

相关推荐
国科安芯7 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
茯苓gao9 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉12 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者13 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间14 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious14 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng18 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计19 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu19 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu20 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32