ADC(Analog-Digital Converter)为模拟-数字转换器,可以将引脚上连续变化的电压值等效为数字变量。
12位为其分辨率0~2^12-1,将能够检测到的电压范围通过线性等效为0-4095其中的一个数字变量,分辨率越高越精确。
1us为转换时间
实现原理:
通过通道选择开关选择输入引脚,然后通过编码DAC实现等效电压,然后将引脚输入电压与编码产生的电压相比较。通过2分法查找,直到编码电压与引脚输入电压相等,此时引脚输入电压的编码就和预编码相同。
一般将参考电压与VDDA,VSSA模拟电源相连。需要时钟使能和START开始信号。转换结束会将EOC信号置位。
输入通道可选外部输入和内部输入,并且可以选择进入规则组还是注入组。
规则组可以同时转换16个通道,但是只有一个数据寄存器,也就是只能输出一个数据。可以通过DMA寄存器缓存。
注入组可以同时转换4个通道,且有4个数据寄存器,即可以输出四个数据。
触发源的选择可以选择软件触发和硬件触发,如果为软件触发需要随时进中断,比较影响效率。
需要配置GPIO口,ADC转换器,时钟使能,中断。
转换模式的介绍:连续/单次----扫描/非扫描 排列组合共有四种转换模式
连续转换,非扫描模式,只能选择一个通道,触发一次即可,每次转换之间不需要对EOC进行操作,进行一次转换后接着进行下一次转换,需要读取值的时候直接读就行。
单次转换,扫描模式:扫描即可进行多个通道的转换,单次即在每次的所有通道都转换结束后,EOC置位,本次转换结束,需要再次触发才能开始下一次的转换。
总而言之,单次/连续 对应着是否能够连续不断的进行转换
扫描/非扫描 即每次转换可以转换多少个通道。
数据有两种对齐方式,一般选择右对齐,不会改变读取值
如果对应精度要求不太高,可以选择左对齐然后把前8位取出来进行比较,这样就是舍弃了后四位的精度。
代码部分:
首先配置输入GPIO和ADC1的时钟
然后配置ADC1转换器的预分频值。
然后配置GPIO的模式,这里注意选择GPIO_PIN_AIN,该模式为模拟输入的专属模式
然后配置ADC1转换器,使能
校准部分文章来源:https://www.toymoban.com/news/detail-836502.html
与ADC相关的取值函数,如果只需要一个通道,那么可以在ADC初始化函数中选择通道和他的规则组模式。如果需要多个通道,则需要给ADC取值函数一个形参用于确定需要转换的通道。然后利用该参数选择当前转换的通道和规则组模式。然后触发转换,直到转换结束会产生信号EOC,如果EOC置位了就可以将该值返回出去。文章来源地址https://www.toymoban.com/news/detail-836502.html
ADC模块相关函数
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //ADC专属模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
GPIO_Init(GPIOA,&GPIO_InitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE; //连续扫描 扫描enable/非扫描
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_InitStructure.ADC_NbrOfChannel=1; //通道数目
ADC_InitStructure.ADC_ScanConvMode=DISABLE; //扫描模式,连续enable/单次
ADC_Init(ADC1,&ADC_InitStructure);
ADC_Cmd(ADC1,ENABLE);
//校准部分
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1)==SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1)==SET);
}
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5); //规则组模式选择,通道选择
ADC_SoftwareStartConvCmd(ADC1,ENABLE); //软件触发
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET); //规则组转换完成
ADC_GetConversionValue(ADC1);
}
主函数调用函数:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "AD.h"
uint8_t Keynum;
uint16_t AD0;
uint16_t AD1;
uint16_t AD2;
uint16_t AD3;
int main()
{
OLED_Init();
AD_Init();
OLED_ShowString(1,1,"AD0:");
OLED_ShowString(2,1,"AD1:");
OLED_ShowString(3,1,"AD2:");
OLED_ShowString(4,1,"AD3:");
while(1)
{
AD0=AD_GetValue(ADC_Channel_0); //传不同的通道进去
AD1=AD_GetValue(ADC_Channel_1);
AD2=AD_GetValue(ADC_Channel_2);
AD3=AD_GetValue(ADC_Channel_3);
OLED_ShowNum(1,5,AD0,4);
OLED_ShowNum(2,5,AD1,4);
OLED_ShowNum(3,5,AD2,4);
OLED_ShowNum(4,5,AD3,4);
Delay_ms(100);
}
}
到了这里,关于stm32-ADC转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!