zoukankan      html  css  js  c++  java
  • STM32F0 中 ADC 多通道转换结果相同的问题

    前言

    前段时间调试 STM32F030 的 ADC,在多通道转换时遇到了奇怪的问题,使用官方的例程和库函数连续转换多个 ADC 通道,得到的几个通道的结果是一样的,解决办法参考了 关于STM32F0系列多路ADC单独采样数据相同问题的处理,在此表示感谢。

    记录

    在官方库的例程 ADC_BasicExample 中的初始化和转换方法如下

    ADC_InitTypeDef     ADC_InitStructure;
    GPIO_InitTypeDef    GPIO_InitStructure;
    
    /* GPIOC Periph clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    
    /* ADC1 Periph clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    
    /* Configure ADC Channel11 as analog input */
    #ifdef USE_STM320518_EVAL
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
    #else
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
    #endif /* USE_STM320518_EVAL */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
      
    /* ADCs DeInit */  
    ADC_DeInit(ADC1);
    
    /* Initialize ADC structure */
    ADC_StructInit(&ADC_InitStructure);
    
    /* Configure the ADC1 in continuous mode with a resolution equal to 12 bits  */
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
    ADC_Init(ADC1, &ADC_InitStructure); 
    
    /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ 
    #ifdef USE_STM320518_EVAL
    ADC_ChannelConfig(ADC1, ADC_Channel_11 , ADC_SampleTime_239_5Cycles);
    #else
    ADC_ChannelConfig(ADC1, ADC_Channel_10 , ADC_SampleTime_239_5Cycles);
    #endif /* USE_STM320518_EVAL */
    
    /* ADC Calibration */
    ADC_GetCalibrationFactor(ADC1);
    
    /* Enable the ADC peripheral */
    ADC_Cmd(ADC1, ENABLE);     
    
    /* Wait the ADRDY flag */
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); 
    
    /* ADC1 regular Software Start Conv */ 
    ADC_StartOfConversion(ADC1);
    
    while (1)
    {
        /* Test EOC flag */
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
        
        /* Get ADC1 converted data */
        ADC1ConvertedValue =ADC_GetConversionValue(ADC1);
        
        /* Compute the voltage */
        ADC1ConvertedVoltage = (ADC1ConvertedValue *3300)/0xFFF;
        
        /* Display converted data on the LCD */
        Display();
    }
    

    可见库函数中切换通道是使用 ADC_ChannelConfig(ADC1, ADC_Channel_11, ADC_SampleTime_239_5Cycles),在库函数中 ADC_ChannelConfig 函数源码如下

    void ADC_ChannelConfig(ADC_TypeDef* ADCx, uint32_t ADC_Channel, uint32_t ADC_SampleTime)
    {
        uint32_t tmpreg = 0;
    
        /* Check the parameters */
        assert_param(IS_ADC_ALL_PERIPH(ADCx));
        assert_param(IS_ADC_CHANNEL(ADC_Channel));
        assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
    
        /* Configure the ADC Channel */
        ADCx->CHSELR |= (uint32_t)ADC_Channel;
    
        /* Clear the Sampling time Selection bits */
        tmpreg &= ~ADC_SMPR1_SMPR;
    
        /* Set the ADC Sampling Time register */
        tmpreg |= (uint32_t)ADC_SampleTime;
    
        /* Configure the ADC Sample time register */
        ADCx->SMPR = tmpreg ;
    }
    

    其中 ADCx->CHSELR |= (uint32_t)ADC_Channel 对寄存器赋值使用了“|”,这会造成下一次循环转换时仍然转换最高位通道
    解决办法是,在每次调用 ADC_ChannelConfig 之后,再对寄存器写入

    uint16_t ADC_Get_Result(uint32_t ch)
    {
        ADC_ChannelConfig(ADC1, ch, ADC_SampleTime_239_5Cycles);
        ADC1->CHSELR = ch;
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)){};
        ADC_StartOfConversion(ADC1);
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET){};
        return ADC_GetConversionValue(ADC1)&0x00000fff;
    }
    
  • 相关阅读:
    权限设计
    ts infer关键字
    Array初始化 以及 Array.prototype.map()的一些问题
    同步、异步、事件循环
    Spring学习笔记(一)
    【面试】关于get和post两种方法的不同。
    【算法】背包问题
    当你在浏览器输入一个网址(如http://www.taobao.com),按回车之后发生了什么?
    数据库语句复习笔记
    【算法】雀魂启动(笔试题)
  • 原文地址:https://www.cnblogs.com/HintLee/p/9802024.html
Copyright © 2011-2022 走看看