STM32 ADC转换速度(以F103为例)

文章目录

  • 系统时间查看
  • ADC转换时间
  • 采集精度
  • 提高稳定性
  • 示例代码

系统时间查看

STM32 ADC转换速度(以F103为例)_第1张图片
ADC挂在APB2上,对应的时钟为PCLK2,由系统时钟SYSCLK 分频得到,一般不做分频,也就是说ADC模块的时钟等于系统时钟,F103也就是72MHz,如下代码也可获取并查看:

RCC_ClocksTypeDef get_rcc_clock;
RCC_GetClocksFreq(&get_rcc_clock);

STM32 ADC转换速度(以F103为例)_第2张图片

ADC转换时间

STM32 ADC转换速度(以F103为例)_第3张图片
手册中也有提到ADC的频率不能超过14MHz,也就是说F103需要至少6分频(最低只有这个分频系数h合适,再有就是4分频已经超过14MHz)。
转化时间计算公式为:
Tconv = Sampling time + 12.5 cycles
如果ADC配置如下:

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);

ADC的工作频率为:72MHz/6 = 12MHz
采样周期数为:239.5+12.5=252
总时间为:1000000us/12000000Hz*252=21us
也就是ADC转换一次需要耗时21us。

采集精度

VREF参考电压值3.3V情况下,12位采集精度如果用于采集3.3V电压,那么3300mV/4095≈0.8mV,也就是说理想情况下最多达到0.8mV的识别精度。STM32单片机有一个内部的参照电压,相当于一个标准电压测量点,在芯片内部连接到ADC1的通道17:
STM32 ADC转换速度(以F103为例)_第4张图片
也就是说可以通过这个通道对其余ADC通道采集的值进行偏移校准,通过内部参考电压校准的话需要多开一路内部ADC1_IN17采样通道.(以12位采样精度为例):
V c h x = A D c h x ∗ ( V r e f i n t / A D r e f i n t ) Vchx = ADchx * (Vrefint/ADrefint) Vchx=ADchx(Vrefint/ADrefint)
V c h x Vchx Vchx:通过计算得出的实际电压值
V r e f i n t Vrefint Vrefint:ADC1_IN17通道采集的ADC值
A D c h x ADchx ADchx:需要测量的ADC通道采样值
A D r e f i n t ADrefint ADrefint:如果是12位采样精度:ADrefint=4095*(1.2/3.3),其中1.2是内部参考电压,这个电压基本不会随着外部供电电压的变化而变化,
STM32 ADC转换速度(以F103为例)_第5张图片
公式中的3.3是单片机的Vref引脚接的电压,这个引脚接的电压也决定ADC的测量范围,如果接的是3.3V,12位采样精度:采样值为2048就表示1.65V,如果接的是2V,采样值为2048就表示1V:
STM32 ADC转换速度(以F103为例)_第6张图片

提高稳定性

一般也就是硬件和软件两个方面,硬件上可在ADC引脚与GND之间跨接一个1uF的电容,或者选择适合自己采集信号的滤波器。软件方面也是只能选择自己合适的软件滤波器。

示例代码

如下是F103的ADC1通道1的DMA使用(PA1引脚),连续自动转换。

uint16_t ADC_Data;

void ADC_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	 
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
	 
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	DMA_DeInit(DMA1_Channel1);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);;//ADC地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Data; //内存地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //方向(从外设到内存)
	DMA_InitStructure.DMA_BufferSize = 1; //传输内容的大小
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //内存地址固定
	DMA_InitStructure.DMA_PeripheralDataSize =	DMA_PeripheralDataSize_HalfWord ; //外设数据单位
	DMA_InitStructure.DMA_MemoryDataSize =	DMA_MemoryDataSize_HalfWord ; //内存数据单位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //DMA模式:循环传输
	DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //优先级:高
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存的传输
	 
	DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA1的1通道
	DMA_Cmd(DMA1_Channel1,ENABLE);
	 
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式
	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);
	 
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC时钟,为PCLK2的6分频,即12MHz
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);//配置ADC1通道1为239.5个采样周期 239.5 + 12.5 = 252
	//21微妙
	 
	ADC_DMACmd(ADC1,ENABLE);
	ADC_Cmd(ADC1,ENABLE);
	 
	ADC_ResetCalibration(ADC1);//复位校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成
	 
	ADC_StartCalibration(ADC1);//ADC校准
	while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
	 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//由于没有采用外部触发,所以使用软件触发ADC转换
}

你可能感兴趣的:(单片机)