STM32H743 ADC差分输入的问题

2019-07-20 01:35发布

本帖最后由 爱芝麻的苹果Z 于 2019-5-31 09:13 编辑

使用STM32板载ADC,均采用差分输入模式,引脚是PA6、7和PC4、5,查手册后选择了ADC1 的3通道和ADC2的4通道,分别差分输入。
现象为:
测量值在1.2V以上时都是正确的,0-1.2V间是固定的测不准,且是周期性的出现。在1.2V、0.8V、0.4V这几个点之间出现跳变。
测负电压是对应的,也就是说测-3到-1.2V之间都是正确的,在-1.2V到0V间都是错的。
采样低电平0V高电平3V的正弦信号,结果如下:
untitled.jpg

ADC代码配置如下:
ADC_HandleTypeDef ADC1_Handler;//ADC¾ä±ú
ADC_HandleTypeDef ADC2_Handler;//ADC¾ä±ú
u8 ch_flag=0;
//3õê¼»ˉADC
//ch: ADC_channels
//í¨μàÖμ 0~16è¡Öμ·¶Î§Îa£oADC_CHANNEL_0~ADC_CHANNEL_16
void MY_ADC_Init(void)
{         
        //ADCÄ£ê½3õê¼»ˉ
    ADC1_Handler.Instance=ADC1;
    ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;                                                 //4·ÖÆ죬ADCCLK=PER_CK/4=64/4=16MHZ
    ADC1_Handler.Init.Resolution=ADC_RESOLUTION_16B;                                                           //16λÄ£ê½
    ADC1_Handler.Init.ScanConvMode=DISABLE;                                                                    //é¨ÃèÄ£ê½
    ADC1_Handler.Init.EOCSelection=ADC_EOC_SINGLE_CONV;                                                                       //1رÕEOCÖD¶ÏADC_EOC_SINGLE_CONV
    ADC1_Handler.Init.LowPowerAutoWait=DISABLE;                                                                                                                //×Ô¶ˉμí1|oÄ1رՠ                               
    ADC1_Handler.Init.ContinuousConvMode=DISABLE;                                                               //á¬Dø×a»»
    ADC1_Handler.Init.NbrOfConversion=1;                                                                //2¸ö×a»»Ôú1æÔòDòáDÖD  
    ADC1_Handler.Init.DiscontinuousConvMode=DISABLE;                                                    //½ûÖ12»á¬Dø2éÑùÄ£ê½
    ADC1_Handler.Init.NbrOfDiscConversion=0;                                                                   //2»á¬Dø2éÑùí¨μàêyÎa0
    ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START;                                              //èí¼t′¥·¢
    ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;        //ê1óÃèí¼t′¥·¢
    ADC1_Handler.Init.BoostMode=ENABLE;                                                                                                                                                //BOOTÄ£ê½1رÕ
    ADC1_Handler.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN;                                                                                //óDDÂμÄêy¾YμÄËàoóÖ±½ó¸2¸Çμô¾éêy¾Y
    ADC1_Handler.Init.OversamplingMode=DISABLE;                                                                                                                //1y2éÑù1رÕ
    ADC1_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DR;                  //1æÔòí¨μàμÄêy¾Y½ö½ö±£′æÔúDR¼Ä′æÆ÷àïÃæ
    HAL_ADC_Init(&ADC1_Handler);                                                                         //3õê¼»ˉ

    HAL_ADCEx_Calibration_Start(&ADC1_Handler,ADC_CALIB_OFFSET,ADC_DIFFERENTIAL_ENDED); //ADCD£×¼
    ADC2_Handler.Instance=ADC2;
    ADC2_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;                                                 //4·ÖÆ죬ADCCLK=PER_CK/4=64/4=16MHZ
    ADC2_Handler.Init.Resolution=ADC_RESOLUTION_16B;                                                           //16λÄ£ê½
    ADC2_Handler.Init.ScanConvMode=DISABLE;                                                                    //é¨ÃèÄ£ê½
    ADC2_Handler.Init.EOCSelection=ADC_EOC_SINGLE_CONV;                                                                       //1رÕEOCÖD¶ÏADC_EOC_SINGLE_CONV
    ADC2_Handler.Init.LowPowerAutoWait=DISABLE;                                                                                                                //×Ô¶ˉμí1|oÄ1رՠ                               
    ADC2_Handler.Init.ContinuousConvMode=DISABLE;                                                               //á¬Dø×a»»
    ADC2_Handler.Init.NbrOfConversion=1;                                                                //2¸ö×a»»Ôú1æÔòDòáDÖD  
    ADC2_Handler.Init.DiscontinuousConvMode=DISABLE;                                                    //½ûÖ12»á¬Dø2éÑùÄ£ê½
    ADC2_Handler.Init.NbrOfDiscConversion=0;                                                                   //2»á¬Dø2éÑùí¨μàêyÎa0
    ADC2_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START;                                              //èí¼t′¥·¢
    ADC2_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;        //ê1óÃèí¼t′¥·¢
    ADC2_Handler.Init.BoostMode=ENABLE;                                                                                                                                                //BOOTÄ£ê½1رÕ
    ADC2_Handler.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN;                                                                                //óDDÂμÄêy¾YμÄËàoóÖ±½ó¸2¸Çμô¾éêy¾Y
    ADC2_Handler.Init.OversamplingMode=DISABLE;                                                                                                                //1y2éÑù1رÕ
    ADC2_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DR;                  //1æÔòí¨μàμÄêy¾Y½ö½ö±£′æÔúDR¼Ä′æÆ÷àïÃæ
    HAL_ADC_Init(&ADC2_Handler);                                                                         //3õê¼»ˉ

    HAL_ADCEx_Calibration_Start(&ADC2_Handler,ADC_CALIB_OFFSET,ADC_DIFFERENTIAL_ENDED); //ADCD£×¼
}

//ADCμ×2ãÇy¶ˉ£¬òy½ÅÅäÖã¬ê±Öóê1Äü
//′Ëoˉêy»á±»HAL_ADC_Init()μ÷óÃ
//hadc:ADC¾ä±ú
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC12_CLK_ENABLE();           //ê1ÄüADC1/2ê±Öó
    __HAL_RCC_GPIOC_CLK_ENABLE();                        //¿aÆôGPIOCê±Öó
   __HAL_RCC_GPIOA_CLK_ENABLE();                        //¿aÆôGPIOAê±Öó
    __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); //ADCíaéèê±ÖóÑ¡Ôñ
        
    GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_5;            //PC4 5
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //Ä£Äa
    GPIO_Initure.Pull=GPIO_NOPULL;          //2»′øéÏÏÂà-
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
        
    GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7;            //PA6 7
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //Ä£Äa
    GPIO_Initure.Pull=GPIO_NOPULL;          //2»′øéÏÏÂà-
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);        
}

//»ñμÃADCÖμ
//ch: í¨μàÖμ 0~16£¬è¡Öμ·¶Î§Îa£oADC_CHANNEL_0~ADC_CHANNEL_16
//·μ»ØÖμ:×a»»½á1û
u16 Get_Adc1(u32 ch,u32 rank)   
{
    ADC_ChannelConfTypeDef ADC1_ChanConf;

    ADC1_ChanConf.Channel=ch;                                   //í¨μà
    ADC1_ChanConf.Rank=rank;                          //1¸öDòáD ADC_REGULAR_RANK_1
    ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5;              //2éÑùê±¼ä      
    ADC1_ChanConf.SingleDiff=ADC_DIFFERENTIAL_ENDED;                                  //2î·Ö2é¼ˉADC_DIFFERENTIAL_ENDED                          
    ADC1_ChanConf.OffsetNumber=ADC_OFFSET_NONE;                     
    ADC1_ChanConf.Offset=0;  
        
    HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //í¨μàÅäÖÃ

    HAL_ADC_Start(&ADC1_Handler);                               //¿aÆôADC
        
    HAL_ADC_PollForConversion(&ADC1_Handler,10);                //ÂÖÑˉ×a»»
        return (u16)HAL_ADC_GetValue(&ADC1_Handler);                    //·μ»Ø×î½üò»′ÎADC11æÔò×éμÄ×a»»½á1û
}

u16 Get_Adc2(u32 ch,u32 rank)   
{
    ADC_ChannelConfTypeDef ADC2_ChanConf;

    ADC2_ChanConf.Channel=ch;                                   //í¨μà
    ADC2_ChanConf.Rank=rank;                          //1¸öDòáD ADC_REGULAR_RANK_1
    ADC2_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5;              //2éÑùê±¼ä      
    ADC2_ChanConf.SingleDiff=ADC_DIFFERENTIAL_ENDED;                                  //2î·Ö2é¼ˉADC_DIFFERENTIAL_ENDED                          
    ADC2_ChanConf.OffsetNumber=ADC_OFFSET_NONE;                     
    ADC2_ChanConf.Offset=0;  
        
    HAL_ADC_ConfigChannel(&ADC2_Handler,&ADC2_ChanConf);        //í¨μàÅäÖÃ

    HAL_ADC_Start(&ADC2_Handler);                               //¿aÆôADC
        
    HAL_ADC_PollForConversion(&ADC2_Handler,10);                //ÂÖÑˉ×a»»
        return (u16)HAL_ADC_GetValue(&ADC2_Handler);                    //·μ»Ø×î½üò»′ÎADC11æÔò×éμÄ×a»»½á1û
}


大家可以看到我用的很笨的办法来实现 就是怕出现问题 但是仍然无法成功。

定时器是10ms触发一次,通过定时器进行采样。中断服务程序为:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM3_Handler))
    {
        adcx1=Get_Adc1(ADC_CHANNEL_3,ADC_REGULAR_RANK_1);//»ñè¡í¨μà19μÄ×a»»Öμ
        adcx2=Get_Adc2(ADC_CHANNEL_4,ADC_REGULAR_RANK_1);//»ñè¡í¨μà19μÄ×a»»Öμ
        temp1=(float)(3300*((2.0*adcx1/65536.0)-1.0));         //»ñ衼ÆËãoóμÄ′øD¡êyμÄêμ¼êμçÑ1Ö죬±èèç3.1111
        temp2=(float)(3300*((2.0*adcx2/65536.0)-1.0));         //»ñ衼ÆËãoóμÄ′øD¡êyμÄêμ¼êμçÑ1Ö죬±èèç3.1111        
     }               
}


求助各位大佬。万分感谢



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。