一、什么是ADC采集?

        首先,让我们来了解一下什么是ADC采集。ADC,即模拟到数字转换器,它的作用是将连续的模拟信号转换为离散的数字信号。简单来说,就是通过ADC,我们可以将现实世界中的模拟信号(如温度、压力、电压等)转换为数字信号,以便在微控制器中进行处理和分析。

二、STM32F103C8T6的ADC特点

        STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,它内置了ADC模块,具有以下特点:

  1. 12位分辨率:可以提供高达4096个不同的数字值,以表示模拟信号的细微变化。
  2. 多个通道:具有多个ADC通道,可以同时或分别采集多个模拟信号。
  3. 灵活的配置选项:可以通过配置ADC的工作模式、采样时间等参数,来满足不同的应用需求。

三、ADC采集步骤

  1. 配置ADC模块的时钟和引脚

        在STM32中,使用任何外设之前都需要先配置其时钟。因此,我们需要在RCC寄存器中设置ADC的时钟源。同时,还需要在GPIO寄存器中设置ADC引脚的模式和速度。

        2.配置ADC模块的参数

        在ADC_CR1和ADC_CR2寄存器中设置采样时间、采样顺序、转换模式等参数。这些参数将决定ADC的工作方式和性能。例如,你可以设置ADC为单次转换模式或连续转换模式,设置采样时间以优化ADC的精度和速度等。

        3.启动ADC采样

        在ADC_CR2寄存器中设置SWSTART位,启动ADC转换。此时,ADC将开始采集模拟信号并将其转换为数字信号。

        4.等待ADC转换完成

        在ADC_SR寄存器中轮询EOC位,等待ADC转换完成。当ADC完成一次转换后,EOC位将被置1,表示转换结果已经准备好可以读取了。

        5.读取ADC转换结果

        通过ADC_DR寄存器读取转换结果。这个寄存器中存储了ADC转换后的数字值,我们可以将其读取出来进行处理和分析。

        6.重复以上步骤实现多通道模拟信号的采集

        如果需要采集多个模拟信号,可以重复以上步骤,并在每次采集前重新配置ADC的参数以选择不同的通道。

四、具体实现代码

#include "stm32f10x.h" 

void ADC1_Config(void){
    
    GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
    
    //配置引脚  GPIOA4 次引脚对应 adc1/2 通道4
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;		 
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
    //配置ADC参数
	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_Div8);//配置ADC时钟,为PCLK2的8分频,即9Hz
	ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_13Cycles5);//配置ADC1通道4为13.5个采样周期 
    //启动ADC1
	ADC_Cmd(ADC1,ENABLE);
}

u16 adc_value(u8 thoroughfare)
{
	 ADC_RegularChannelConfig(ADC1,thoroughfare,1,ADC_SampleTime_55Cycles5);
     //软件触发开始转换 (产生触发信号)
	 ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	 //判断转换EOC是否结束,检测EOC标志位
	 while(!ADC_GetFlagStatus (ADC1, ADC_FLAG_EOC));
	 //获取最近一次ADC的转换值
	 return ADC_GetConversionValue (ADC1);
}

int main(){
   //初始化ADC
   ADC1_Config();
   //获取ADC值
   u16 ad_val = adc_value(4);   //读取通道4的ADC值
   //把获取的ADC值转换为实际的电压值
   float voltage = ad_val /4096.0f * 3.3;
   while(true){

       //.......

  }
}

五、注意事项

在进行ADC采集时,需要注意以下几点:

  1. ADC模块的转换精度取决于时钟源的稳定性和采样时间的设定。因此,在选择时钟源和设置采样时间时需要谨慎考虑。
  2. ADC输入电压范围在0~3.3V之间。如果测取的电压超过此范围,需要进行分压处理,可以通过串联电阻进行分压。
  3. 在实际应用中,通常需要对采样数据进行处理和滤波,以确保数据的准确性和稳定性。例如,可以使用滑动平均滤波等方法来平滑数据并减少噪声的影响。
  4. 在进行多通道采集时,需要注意通道之间的切换时序和数据处理方式,以确保数据的正确性和实时性。可以使用DMA(直接内存访问)等技术来优化数据传输和处理效率。