织梦网站手机版怎么做,外贸网站使用攻略,电子商务网站和开发新闻类网站,一个商城网站开发周期这篇文章是嵌入式中我通过大量资料 整合成了一份 系统完整、层次清晰的 ADC 模数转换原理解析 文档。
这里系统地梳理了 STM32F1 系列 ADC 模数转换的核心资料#xff0c;包括#xff1a;
1.原理 特性
2.通道配置
3.模式选择#xff08;单次/连续/扫描#xff09;
4.关键寄…这篇文章是嵌入式中我通过大量资料 整合成了一份 系统完整、层次清晰的 ADC 模数转换原理解析 文档。
这里系统地梳理了 STM32F1 系列 ADC 模数转换的核心资料包括
1.原理 特性
2.通道配置
3.模式选择单次/连续/扫描
4.关键寄存器与时序
5.全套库函数调用方式
6.提供示例实验代码STM32F1 系列 ADC 模数转换原理详解参考资料
STM32F1xx官方资料《STM32中文参考手册V10》-第11章 模拟/数字转换ADC)第一部分STM32 ADC 基本原理
什么是 ADC
ADCAnalog to Digital Converter 是一种将模拟电压信号转换为数字信号的模块。在 STM32 中ADC 是片上外设可将 03.3V 的电压转换为 12 位数值04095。
ADC 指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
为什么需要 ADC
因为 MCU如 STM32只能处理 数字信号0 和 1而现实世界中的信号多数是连续的模拟量如模拟信号数字处理需求温度需要转换为数字量电压需要转为数字量光照强度数字化后进行计算电流数字化后保护电路ADC 的基本工作过程模拟信号 → 数字值
将输入电压 VIN 转换为一个 数字码值范围为 0 ~ 2ⁿ - 1其中 n 为 ADC 的分辨率。例如在 STM32F1 中ADC 是 12 位所以
数字范围0 ~ 40952¹² - 1输入范围VREF- ~ VREF一般为 0V ~ 3.3VSTM32F10x ADC特点12位逐次逼近型的模拟数字转换器。
最多带3个ADC控制器
最多支持18个通道可最多测量16个外部和2个内部信号源。
支持单次和连续转换模式
转换结束注入转换结束和发生模拟看门狗事件时产生中断。
通道0到通道n的自动扫描模式
自动校准
采样间隔可以按通道编程
规则通道和注入通道均有外部触发选项
转换结果支持左对齐或右对齐方式存储在16位数据寄存器
ADC转换时间最大转换速率 1us。最大转换速度为1MHz在ADCCLK14M采样周期为1.5个ADC时钟下得到。
ADC供电要求2.4V-3.6V
ADC输入范围VREF- ≤ VIN ≤ VREF电压转换公式
V (ADC_Value / 4096.0) * Vref假设 Vref 3.3VADC_Value 2048则
V 2048 / 4096 * 3.3 1.65V
特性描述转换精度12位0~4095架构逐次逼近型SAR控制器个数最多 3 个ADC1~ADC3通道数量最多 18 个16个外部 温度 VREF模式单次 / 连续 / 扫描 / 注入对齐方式左对齐 / 右对齐校准功能支持自动校准时钟要求ADCCLK ≤ 14MHz第二部分通道与引脚对应关系如下图示
STM32F10x大容量芯片带3个ADC控制器其中144脚芯片因为带PF脚所以多5个通道为21个外部通道。小于144脚芯片只有16个外部通道。
【转换通道结构】
通道类型 最大通道数 特点
规则通道 16 个 正常顺序转换
注入通道 4 个 类似中断处理可打断规则通道
内部通道 2 个 温度ch16、VREFch17STM32F10x系列芯片ADC通道和引脚对应关系ADC引脚ADC 模块框图ADC 寄存器结构 模式ADC的模块包含输入多路选择器模拟至数字转换器SAR控制逻辑触发、注入/规则选择数据寄存器ADC_DR、JDRx状态寄存器ADC_SR核心模块说明模块功能多路复用器MUX选择当前要转换的通道采样保持电路暂存输入电压稳定后再转换SAR ADC逐次逼近型 ADC12 位精度控制器控制转换模式、触发方式、通道顺序等数据缓冲存储转换结果ADC_DRSTM32通道组① 规则通道组 相当正常运行的程序。最多16个通道。
规则通道和它的转换顺序在ADC_SQRx寄存器中选择规则组转换的总数应写入ADC_SQR1寄存器的 L[3:0] 中。
② 注入通道组 相当于中断。最多4个通道。
注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转化的总数应写入ADC_JSQR寄存器的 L[1:0] 中。STM32F1的ADC的各通道可以单次连续扫描或者间断模式执行。第三部分模式选择单次/连续/扫描
转换模式模式描述单次转换Single一次启动 → 一次转换手动触发连续转换Continuous自动重复转换同一通道扫描模式Scan多通道自动轮询注入模式Injected类似中断方式打断规则组转换软件触发SWSTART 启动程序调用触发外部触发定时器、外部引脚等外设触发EXTSEL单次转化 VS 连续转换扫描模式ADC中断ADC时钟配置
RCC_ADCCLKConfig(RCC_PCLK2_Div6); 不要让ADC时钟超过14MHz否则可能不准。第四部分关键寄存器与时序ADC 核心寄存器说明简表寄存器作用ADC_CR1模式选择扫描模式使能EOC中断ADC_CR2启动控制、触发源、数据对齐、CONTADC_SQRx通道顺序配置ADC_SMPRx通道采样时间配置ADC_JSQR注入系列寄存器ADC_DR转换结果数据寄存器ADC_JDR注入通道数据寄存器ADC_SR状态标志EOC、AWD等ADC_CR1寄存器在扫描模式下由ADC_SQRx或者ADC_JSQRx寄存器选中的通道被转换。如果设置了EOCIE或者JEOCIE在最后一个通道转换完毕后才会产生EOC或者JEOC中断。ADC_CR2寄存器数据对齐方式ADC_SMPR1寄存器ADC_SMPR2寄存器ADC的采样时间最小采样时间1us(ADC时钟14MHz采样周期为1.5周期下得到
采样时间Sample Time选择SMPx 设置值采样时间周期说明0001.5快速采样低精度111239.5高阻抗信号推荐
总转换时间 采样周期 12.5 周期ADC 对输入电压采样的时间长度单位为 ADC 时钟周期如 1.5 周期、7.5 周期等。
采样时间越长精度越高、可适配输入阻抗大的传感器。ADC 采样时间建议采样时间必须根据输入阻抗、电压变化速度、ADC 时钟等参数合理选择。
采样周期建议用途1.5 周期高频快速采样精度低输入阻抗需小71.5 周期推荐默认239.5 周期输入阻抗高/慢信号更稳✅ 示例读取 PA1 电压值
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_GPIO_Init(); // PA1 模拟输入
ADC1_SingleChannel_Init();ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
uint16_t value ADC_GetConversionValue(ADC1);
float voltage (value / 4096.0f) * 3.3f;ADC_SQRxADC_SQR1/SQR2/SQR3规则序列寄存器ADC_JSQR注入系列寄存器ADC_DR规则通道数据寄存器ADC_JDR注入通道数据寄存器ADC_SR状态寄存器配置流程1. RCC 时钟设置
ADC 时钟不能超 14MHz推荐如下设置
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72MHz/6 12MHz2. ADC 初始化结构体
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode 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);3. 通道配置 采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);通道按 Rank 顺序决定转换顺序
采样时间越长精度越高输入阻抗越能适应4. 启动转换流程
// 开启ADC
ADC_Cmd(ADC1, ENABLE);// 校准
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));// 软件启动转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);// 等待完成
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));// 读取结果
uint16_t value ADC_GetConversionValue(ADC1);第五部分全套库函数调用方式
常用库函数
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_DeInit(ADC_TypeDef* ADCx)
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
函数功能ADC_Init()初始化结构体配置ADC_Cmd()启用 ADCADC_ResetCalibration() / StartCalibration()复位校准 / 启用校准ADC_SoftwareStartConvCmd()软件触发ADC_RegularChannelConfig()配置通道顺序与采样时间ADC_SoftwareStartConvCmd()启动转换软件ADC_GetConversionValue()获取转换结果12位右对齐/左对齐ADC初始化函数ADC_Init
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);typedef struct
{uint32_t ADC_Mode;//ADC模式配置ADC_CR1寄存器的位[19:16] DUALMODE[3:0]位FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8SCAN位 FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换ADC_CR2的位1CONTuint32_t ADC_ExternalTrigConv; //触发方式ADC_CR2的位[19:17] EXTSEL[2:0] uint32_t ADC_DataAlign; //对齐方式左对齐还是右对齐ADC_CR2的位11ALIGN uint8_t ADC_NbrOfChannel;//规则通道序列长度ADC_SQR1的位[23:20] L[3:0]
}ADC_InitTypeDef;ADC_InitStructure.ADC_Mode ADC_Mode_Independent;//独立模式ADC_InitStructure.ADC_ScanConvMode DISABLE; //不开启扫描
ADC_InitStructure.ADC_ContinuousConvMode DISABLE;//单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None;//触发软件
ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right;//ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel 1;//顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, ADC_InitStructure); ADC使能函数 ADC_Cmd();
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1ADC使能软件转换函数 ADC_SoftwareStartConvCmd
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx,FunctionalState NewState);ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动ADC 规则通道配置函数ADC_RegularChannelConfig
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 );ADC 获取转换结果函数ADC_GetConversionValue
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);ADC_GetConversionValue(ADC1);//获取ADC1转换结果第六部分这是一个完整的 STM32F103 系列 ADC 实验代码实验目标使用 ADC1 的通道1PA1
采用 单次转换模式
软件触发转换读取电压值
将 ADC 值输出到串口或用作其他逻辑判断项目条件
模拟输入范围VREF- ≤ VIN ≤ VREF默认 VSSA~VDDA
分辨率12 位转换结果范围0 ~ 4095
输入引脚通道 1 → PA1
模式单次转换、软件触发、右对齐
时钟要求ADC 时钟 ≤ 14MHz推荐 RCC_ADCCLKConfig(RCC_PCLK2_Div6)
数据读取方式轮询 ADC_SR.EOC 位或使用中断本例使用轮询使用外设ADC1
GPIOAPA1
RCC时钟配置#include stm32f10x.h// 延时函数用于测试
void delay_ms(uint32_t ms)
{SysTick-LOAD 72000 - 1;SysTick-VAL 0;SysTick-CTRL 0x5;while (ms--){while (!(SysTick-CTRL (1 16)));}SysTick-CTRL 0;
}// UART 打印函数可自行添加// 初始化 PA1 为模拟输入
void ADC_GPIO_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef gpio;gpio.GPIO_Pin GPIO_Pin_1;gpio.GPIO_Mode GPIO_Mode_AIN; // 模拟输入GPIO_Init(GPIOA, gpio);
}// 配置 ADC1 通道1
void ADC1_SingleChannel_Init(void)
{// 1. 开启 ADC1 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);// 2. 设置 ADC 时钟分频PCLK2/6 12MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);// 3. 复位 ADC1ADC_DeInit(ADC1);// 4. 初始化 ADC1ADC_InitTypeDef adc;adc.ADC_Mode ADC_Mode_Independent; // 独立模式adc.ADC_ScanConvMode DISABLE; // 禁用扫描adc.ADC_ContinuousConvMode DISABLE; // 单次转换adc.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; // 软件触发adc.ADC_DataAlign ADC_DataAlign_Right; // 右对齐adc.ADC_NbrOfChannel 1; // 仅一个通道ADC_Init(ADC1, adc);// 5. 使能 ADC1ADC_Cmd(ADC1, ENABLE);// 6. 复位校准ADC_ResetCalibration(ADC1);while (ADC_GetResetCalibrationStatus(ADC1));// 7. 启动校准ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1));
}// 读取 ADC1 通道1 的电压值0~4095
uint16_t ADC1_Read_PA1(void)
{// 1. 配置规则通道ADC1, 通道1, 第1个转换采样时间 239.5周期ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);// 2. 软件触发转换ADC_SoftwareStartConvCmd(ADC1, ENABLE);// 3. 等待转换完成EOC 置位while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));// 4. 读取转换结果return ADC_GetConversionValue(ADC1);
}int main(void)
{SystemInit();ADC_GPIO_Init();ADC1_SingleChannel_Init();uint16_t adc_value;while (1){adc_value ADC1_Read_PA1(); // 读取ADC值0~4095// 比如输出到串口或控制LED亮灭// printf(ADC Value %d\r\n, adc_value);delay_ms(500);}
}ADC 寄存器与控制流程以规则通道为例初始化流程图
流程简化版
模拟输入 → 采样保持电路 → SAR ADC12位 → 数据寄存器ADC_DR↑ |通道选择器MUX 控制逻辑触发、扫描、注入RCC 配置 ADC 时钟
↓
GPIO 配置为模拟输入
↓
ADC_Init() 初始化结构体
↓
ADC 校准ResetCalibration StartCalibration
↓
ADC 配置通道 采样时间
↓
启动转换软件/外部
↓
等待 EOC 标志
↓
读取 ADC_DR 寄存器总结 ADC 配置过程要点步骤操作对应函数或寄存器1设置时钟分频RCC_ADCCLKConfig(RCC_PCLK2_Div6)2初始化 ADCADC_Init()3开启 ADCADC_Cmd(ADC1, ENABLE)4校准 ADCADC_Reset/StartCalibration()5配置通道ADC_RegularChannelConfig()6软件触发ADC_SoftwareStartConvCmd()7等待转换完成ADC_FLAG_EOC8获取数据ADC_GetConversionValue()结果转换公式
// 假设参考电压为 3.3V
float voltage adc_value * 3.3 / 4096;实验完整代码标准库实现模块化
因为在 Keil 软件中函数设计是模块划分的代码整理
实验目的ADC1的通道1PA1)进行单次转化流程
① 开启PA口时钟和ADC1时钟设置PA1为模拟输入。
GPIO_Init();
APB2PeriphClockCmd();
② 复位ADC1同时设置ADC1分频因子。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_DeInit(ADC1);
③ 初始化ADC1参数设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
④ 使能ADC并校准。
ADC_Cmd(ADC1, ENABLE);
⑤ 配置规则通道参数
ADC_RegularChannelConfig();
⑥开启软件转换ADC_SoftwareStartConvCmd(ADC1);
⑦等待转换完成读取ADC值。
ADC_GetConversionValue(ADC1);adc.h
#ifndef _ADC_H_
#define _ADC_H_#include stm32f10x.h
#include stdio.hvoid MX_ADC_Init(void);uint16_t Get_ADC(ADC_TypeDef* ADCx, uint8_t ADC_Channel);#endifadc.c
#include adc.hvoid MX_ADC_Init(void)
{//-------------------------------------GPIO Init---------------------------------------//GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1, ENABLE);GPIO_InitStruct.GPIO_Mode GPIO_Mode_AIN; //配置为模拟输入GPIO_InitStruct.GPIO_Pin GPIO_Pin_0; //配置 0 管脚GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; //翻转速度 50MHzGPIO_Init(GPIOC, GPIO_InitStruct);GPIO_WriteBit(GPIOC, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9, Bit_SET);//-------------------------------------GPIO Init---------------------------------------//RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟 6 分频ADC_InitTypeDef ADC_InitStruct;ADC_InitStruct.ADC_ContinuousConvMode DISABLE; //不使用连续转换ADC_InitStruct.ADC_DataAlign ADC_DataAlign_Right; //ADC 数据右对齐ADC_InitStruct.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动ADC_InitStruct.ADC_Mode ADC_Mode_Independent; //ADC1 和 ADC2 工作在独立模式ADC_InitStruct.ADC_NbrOfChannel 1; //仅使用了通道10。规定了顺序进行规则转换的 ADC 通道的数目。这个数目的取值范围是 1 到 16。ADC_InitStruct.ADC_ScanConvMode DISABLE; //不使用扫描模式ADC_Init( ADC1, ADC_InitStruct);ADC_Cmd( ADC1, ENABLE ); //使能 ADC1ADC_ResetCalibration( ADC1 ); //重置指定的 ADC 的校准寄存器while(ADC_GetResetCalibrationStatus( ADC1 ) SET ){}; //等待校准完成 --ADC 重置校准寄存器的新状态SET 或者 RESETADC_StartCalibration( ADC1 ); //开启校准while(ADC_GetCalibrationStatus( ADC1 ) SET){}; //等待校准完成}uint16_t Get_ADC(ADC_TypeDef* ADCx, uint8_t ADC_Channel)
{ADC_RegularChannelConfig( ADCx, ADC_Channel, 1, ADC_SampleTime_239Cycles5); //配置好ADC的规则通道ADC_SoftwareStartConvCmd( ADCx, ENABLE); //开启ADC转换while(ADC_GetSoftwareStartConvStatus( ADCx ) SET){}; //等待转换完成return ADC_GetConversionValue( ADCx );
}main.c
/********************************************************************************* file Project/STM32F10x_StdPeriph_Template/main.c * author MCD Application Team* version V3.5.0* date 08-April-2011* brief Main program body******************************************************************************* attention** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** h2centercopy; COPYRIGHT 2011 STMicroelectronics/center/h2*******************************************************************************/ /* Includes ------------------------------------------------------------------*/
#include stm32f10x.h
#include stdio.h
#include gpio.h
#include systick.h
#include exti.h
#include usart.h
#include string.h
#include wdg.h
#include tim.h
#include pwm.h
#include adc.hint main()
{
// uint16_t Compare2 0;
// bool Dir 0;uint32_t ADC1_ts 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断使用分组2Systick_Initerupt_Init();MX_EXTI0_Init();MX_USART1_Init(115200);USART1_NVIC_Init(1,1);MX_TIM3_PWM_Init(20000 -1, 72-1); //周期 xx/msMX_ADC_Init();printf(System Init OK! \r\n);while(1){Get_ADC(ADC1, ADC_Channel_10);if(GetTick() - ADC1_ts 500){ADC1_ts GetTick();printf(ADC %d \r\n, Get_ADC(ADC1, ADC_Channel_10));}}
}/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/以上便是 ADC模数转换器基本原理 的系统性说明结合 STM32F1 系列 的实现机制 涵盖 理论、硬件架构、采样机制及转换过程 的原理。
以上欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问我可以提供实战演示或模板库。希望内容能够对你产生帮助