STM32自带13ADC模块,采样精度达到了12位。在STM32F103RBT6中,ADC1ADC2共用一组管脚。总体编程思路如下:

  1. 初始化RCC相关,使能系统时钟,使能功能模块如ADCDMA的时钟。
  2. GPIO相关初始化,比如常用的指示灯,ADC的引脚要设置为输入。
  3. NVIC向量中断的配置,因为这里使用了DMA中断和中断服务程序编写(下例中暂不使用)。
  4. DMA配置(下例中暂不使用)。
  5. ADC初始化。

  相关的通道如下:

通道 ADC1 ADC2 ADC3
通道0 PA0 PA0 PA0
通道1 PA1 PA1 PA1
通道2 PA2 PA2 PA2
通道3 PA3 PA3 PA3
通道4 PA4 PA4 PF6
通道5 PA5 PA5 PF7
通道6 PA6 PA6 PF8
通道7 PA7 PA7 PF9
通道8 PB0 PB0 PF10
通道9 PB1 PB1
通道10 PC0 PC0 PC0
通道11 PC1 PC1 PC1
通道12 PC2 PC2 PC2
通道13 PC3 PC3 PC3
通道14 PC4 PC4
通道15 PC5 PC5
通道16 温度传感器
通道17 内部参考电压

  以下是参考代码,使用ADC1IN0脚:

void ADC_GPIO_Init ( void ) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE );
    GPIO_DeInit ( GPIOA );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /* 设为模拟输入 */
    GPIO_Init ( GPIOA, &GPIO_InitStructure );
}

void ADC_configuration ( void ) {
    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 );
    // ADC_RegularChannelConfig( ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5 );
    ADC_Cmd ( ADC1, ENABLE ); /* 使能或者失能指定的ADC */
    ADC_ResetCalibration ( ADC1 ); /* 重置指定的ADC的校准寄存器 */

    while ( ADC_GetResetCalibrationStatus ( ADC1 ) ); /* 等待校准寄存器初始化 */

    ADC_StartCalibration ( ADC1 ); /* 开始校准 */

    while ( ADC_GetCalibrationStatus ( ADC1 ) ); /* 等待校准完成 */

    ADC_SoftwareStartConvCmd ( ADC1, ENABLE ); /* 使能指定的ADC的软件转换启动功能 */
}

u16 GetADCValue ( u8 ADC_Channel ) { /* ADC_Channel_x 0~17 */
    u16 adc_value;
    ADC_RegularChannelConfig ( ADC1, ADC_Channel, 1, ADC_SampleTime_7Cycles5 );
    ADC_SoftwareStartConvCmd ( ADC1, ENABLE ); /* 使能指定的ADC的软件转换启动功能 */

    /* 检查制定ADC标志位是否置为1,ADC_FLAG_EOC是转换结束标志位 */
    while ( ADC_GetFlagStatus ( ADC1, ADC_FLAG_EOC ) == RESET );

    adc_value = ADC_GetConversionValue ( ADC1 );
    return adc_value; /* 返回最近一次ADCx规则组的转换结果 */
}

  当使用内部温度传感器时,需要使能温度传感器通道:

ADC_TempSensorVrefintCmd ( ENABLE );

温度传感器通道号是ADC_Channel_16,此通道的采样时间调到最大,来保证精度。温度的计算公式如下:

温度(∘C)=V25−VSENSEAvg_Slope+25 温度(^{\circ}C) = \frac{V_{25}-V_{SENSE}}{Avg\_Slope} + 25 (C)=Avg_SlopeV25VSENSE+25

其中V25V_{25}V25VSENSEV_{SENSE}VSENSE25∘C25^{\circ}C25C时的数值;Avg_SlopeAvg\_SlopeAvg_Slope是温度与VSENSEV_{SENSE}VSENSE曲线的平均斜率(单位是mV/∘CmV/^{\circ}CmV/CμV/∘C\mu V/^{\circ}CμV/C)。V25V_{25}V25VSENSEV_{SENSE}VSENSE的典型值分别为1.431.431.434.3mV/∘C4.3mV/^{\circ}C4.3mV/C,则TEMP = (1.43 - Vsense)/0.0043 + 25

  补充说明

  1. STM32ADC可以分为注入组(Injected Channel)和规则组(Regular Channel),规则组放的是常规情况下的检查所需要的数据,注入组放的是特殊情况下的检查所需要的数据(或者是特殊数据),也可以说规则组是主程序,而注入组是中断程序。
  2. 如果你的ADC_CLK越小,即你的AD转换速度越慢,那么AD转换的精度就越高。
  3. 注意STM32ADC功能的触发模块(可允许外部触发,也可以允许内部定时器触发)。
  4. STM32ADC转换模式:单次(对单个端口只转换一次)、连续(对端口连续转换多次)、扫描(对多个端口进行扫描)和中断。
  5. 自动注入(IAUTO)将规则组与注入组规为一组。
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐