标题: STM32F10X ADC原理详解(STM32F103ZET6) [打印本页]

作者: 1U1dyss    时间: 2018-10-2 11:11
标题: STM32F10X ADC原理详解(STM32F103ZET6)
STM32ADC的工作原理
模/数转换器
STM32F10x  ADC特点
12位逐次逼近型的模拟数字转换器。
最多带3个ADC控制器
最多支持18个通道,可最多测量16个外部和2个内部信号源。
支持单次和连续转换模式
转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。
通道0到通道n的自动扫描模式
自动校准
采样间隔可以按通道编程
规则通道和注入通道均有外部触发选项
转换结果支持左对齐或右对齐方式存储在16位数据寄存器
ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)
ADC供电要求:2.4V-3.6V
ADC输入范围:VREF- ≤  VIN  ≤  VREF+

ADC引脚


STM32F10x系列芯片ADC通道和引脚对应关系
由下图可见ADC1的通道0~通道17都有功能,而ADC2的通道16和通道17没有作用,ADC3的通道9、通道14~通道17也没有作用。

STM32通道组
①规则通道组:相当正常运行的程序。最多16个通道。
     规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则
     组转换的总数应写入ADC_SQR1寄存器的L[3:0]中
② 注入通道组:相当于中断。最多4个通道。
     注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组
     里转化的总数应写入ADC_JSQR寄存器的L[1:0]中
STM32F1的ADC的各通道可以单次模式执行,连续模式执行,扫描或者间断模式执行。

       规则通道组                           
含有注入通道的规则通道组



☞单次转化
单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位(只
适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。
一旦选择通道的转换完成:
● 如果一个规则通道被转换:
─  转换数据被储存在16位ADC_DR寄存器中
─  EOC(转换结束)标志被设置
─  如果设置了EOCIE,则产生中断。
● 如果一个注入通道被转换:
─  转换数据被储存在16位的ADC_DRJ1寄存器中
─  JEOC(注入转换结束)标志被设置
─  如果设置了JEOCIE位,则产生中断。
☞连续转换模式
在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。(连续转换会自动开启下一次转换)此模式可通过外部触发启
动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。
每个转换后:
● 如果一个规则通道被转换:
─  转换数据被储存在16位的ADC_DR寄存器中
─  EOC(转换结束)标志被设置
─  如果设置了EOCIE,则产生中断。
● 如果一个注入通道被转换:
─  转换数据被储存在16位的ADC_DRJ1寄存器中
─  JEOC(注入转换结束)标志被设置
─  如果设置了JEOCIE位,则产生中断。


☞扫描模式
此模式用来扫描一组模拟通道。扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM中。而注入通道转换的数据总是存储在ADC_JDRx寄存器中。


ADC中断
规则和注入组转换结束时能产生中断,当模拟看门狗状态位被设置时也能产生中断。它们都有
独立的中断使能位。
注: ADC1 和 ADC2 的中断映射在同一个中断向量上,而 ADC3 的中断有自己的中断向量。
ADC_SR寄存器中有2个其他标志,但是它们没有相关联的中断:
● JSTRT(注入组通道转换的启动)
● STRT(规则组通道转换的启动)
ADC 时钟
由时钟控制器提供的ADCCLK时钟和PCLK2(APB2时钟)同步。RCC控制器为ADC时钟提供一个
专用的可编程预分频器.注:不要让ADC时钟超过14MHz,否则可能不准。


可编程的通道采样时间
ADC使用若干个ADC_CLK周期对输入电压采样,采样周期数目可以通过ADC_SMPR1和
ADC_SMPR2寄存器中的SMP[2:0]位更改。每个通道可以分别用不同的时间采样。
总转换时间如下计算:
T(CONV) = 采样时间+ 12.5个周期
例如:
当ADCCLK=14MHz,采样时间为1.5周期
T(CONV) = 1.5 + 12.5 = 14周期 = 1μs


ADC_SMPR1寄存器和ADC_SMPR2寄存器用来设置通道0~17这18个通道
ADC采样时间——可编程的采样时间
ADC_SQR1/SQR2/SQR3规则序列寄存器
ADC_JSQR注入系列寄存器
ADC_SR状态寄存器


常用库函数
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);ADC的初始化函数
void ADC_DeInit(ADC_TypeDef* ADCx);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);ADC使能函数
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);ADC获取转换结果函数


校准函数:
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_ResetCalibration(ADC1);    //使能复位校准  
while(ADC_GetResetCalibrationStatus(ADC1));    //等待复位校准结束
ADC_StartCalibration(ADC1);     //开启AD校准
while(ADC_GetCalibrationStatus(ADC1));     //等待校准结束


typedef struct
{   
uint32_t ADC_Mode;//ADC模式:配置ADC_CR1寄存器的位[19:16]  :DUALMODE[3:0]位   
FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位   
FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONT   uint32_t ADC_ExternalTrigConv;  //触发方式:ADC_CR2的位[19:17] :EXTSEL[2:0]                   
uint32_t ADC_DataAlign;   //对齐方式:左对齐还是右对齐:ADC_CR2的位11:ALIGN           
uint8_t ADC_NbrOfChannel;//规则通道序列长度:ADC_SQR1的位[23:20]: L[3:0]        
}ADC_InitTypeDef;
例:
void ADC_Init(ADC_TypeDef*ADCx,ADC_InitTypeDef*ADC_InitStruct)
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使能函数ADC_Cmd()
例如:ADC_Cmd(ADC1,ENABLE);//使能指定的ADC1
ADC使能软件转换函数ADC void ADC_SoftwareStartConvCmd();
例如:ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1的软件转换启动
ADC规则通道配置函数voidADC_RegularChannelConfig()
例如:ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);//在ADC1的通道1,规则序列中的第1个转换,采样时间。ADC_RegularChannelConfig(用哪个ADC,哪个通道, 通道在规则序列中的序号, 采样时间);
ADC获取转换结果函数ADC_GetConversionValue();如ADC_GetConversionValue(ADC1);//获取ADC1转换结果


实验一:ADC1的通道1(PA1)进行单次转换
目的:使用库函数的函数来设定使用ADC1的通道1进行A/D转换。
ADC的配置过程如下:
①开启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使能函数
校准使用校准函数
⑤ 配置规则通道参数:      
ADC_RegularChannelConfig();
ADC1的通道1的配置方法:ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5)
⑥开启软件转换:
ADC_SoftwareStartConvCmd(ADC1);
⑦等待转换完成,读取ADC值。   
ADC_GetConversionValue(ADC1);//获取ADC1的转换结果
将上面七个步骤的功能代码写在两个函数中即可实现功能,分别是函数void Adc_Init(void);和函数u16  Get_Adc(u8 ch);
将上面步骤一到步骤四的程序功能代码写在void Adc_Init(void);函数中。
获取转换结果即将实现步骤五到步骤七的功能代码写在u16  Get_Adc(u8 ch);函数中
多次调用u16  Get_Adc(u8 ch)函数读取ADC1的转换结果,再求平均值,将功能代码写在u16 Get_Adc_Average(u8 ch,u8 times)函数中


STM32实现对12V电压的检测
我们现在需要用STM32对12V电压进行检测,判断其是否正确上电。我打算利用STM32的ADC功能,但12V超过了STM32能承受的范围,我们可以用电阻简单分压成3.3V,然后用STM32的ADC引脚直接采样,判断。不要让ADC脚接到5V以上的的电压,会烧坏引脚。



作者: OUFUJIE    时间: 2020-7-2 15:57
如果要采样5---100V的电压信号用内部ADC,分压需求岂不是很大?有没有好一点的解决思路楼主
作者: shijimiaopu    时间: 2020-7-15 10:15
有没有例程可以跑一下?




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1