littleshrimp 发表于 2018-1-22 17:40

【NUCLEO-L4R5ZI评测】STM32的ADC原来可以超频?

先使用TIM1输出160KHz 50%占空比的方波然后将PWM输出连接到ADC的输入用STM32L4R5的ADC测量PWM信号下边是用示波器测量的PWM输出 配置ADCAdcHandle.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV1; AdcHandle.Init.Resolution= ADC_RESOLUTION_12B;sConfig.SamplingTime =ADC_SAMPLETIME_2CYCLES_5; /* ### - 1 - Initialize ADC peripheral #################################### */

AdcHandle.Instance          = ADCx;

if (HAL_ADC_DeInit(&AdcHandle) != HAL_OK)

{

    /* ADC de-initialization Error */

    Error_Handler();

}



AdcHandle.Init.ClockPrescaler      = ADC_CLOCK_SYNC_PCLK_DIV1;      /* Synchronous clock mode, input ADC clock divided by 2*/

AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;            /* 12-bit resolution for converted data */

AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;         /* Right-alignment for converted data */

AdcHandle.Init.ScanConvMode          = DISABLE;                     /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */

AdcHandle.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;         /* EOC flag picked-up to indicate conversion end */

AdcHandle.Init.LowPowerAutoWait      = DISABLE;                     /* Auto-delayed conversion feature disabled */

AdcHandle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode enabled (automatic conversion restart after each conversion) */

AdcHandle.Init.NbrOfConversion       = 1;                           /* Parameter discarded because sequencer is disabled */

AdcHandle.Init.DiscontinuousConvMode = DISABLE;                     /* Parameter discarded because sequencer is disabled */

AdcHandle.Init.NbrOfDiscConversion   = 1;                           /* Parameter discarded because sequencer is disabled */

AdcHandle.Init.ExternalTrigConv      = ADC_SOFTWARE_START;            /* Software start to trig the 1st conversion manually, without external event */

AdcHandle.Init.ExternalTrigConvEdge= ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */

AdcHandle.Init.DMAContinuousRequests = ENABLE;                        /* ADC DMA continuous request to match with DMA circular mode */

AdcHandle.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;      /* DR register is overwritten with the last conversion result in case of overrun */

AdcHandle.Init.OversamplingMode      = DISABLE;                     /* No oversampling */

/* Initialize ADC peripheral according to the passed parameters */

if (HAL_ADC_Init(&AdcHandle) != HAL_OK)

{

    Error_Handler();

}





/* ### - 2 - Start calibration ############################################ */

if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) !=HAL_OK)

{

    Error_Handler();

}



/* ### - 3 - Channel configuration ######################################## */

sConfig.Channel      = ADCx_CHANNEL;                /* Sampled channel number */

sConfig.Rank         = ADC_REGULAR_RANK_1;          /* Rank of sampled channel number ADCx_CHANNEL */

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;   /* Sampling time (number of clock cycles unit) */

sConfig.SingleDiff   = ADC_SINGLE_ENDED;            /* Single-ended input channel */

sConfig.OffsetNumber = ADC_OFFSET_NONE;             /* No offset subtraction */

sConfig.Offset = 0;                                 /* Parameter discarded because offset correction is disabled */

if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)

{

    Error_Handler();

}



/* ### - 4 - Start conversion in DMA mode ################################# */

if (HAL_ADC_Start_DMA(&AdcHandle,

                        (uint32_t *)aADCxConvertedData,

                        ADC_CONVERTED_DATA_BUFFER_SIZE

                     ) != HAL_OK)

{

    Error_Handler();

} 添加DMA中断,断点打在__NOP();上,在__NOP();之前一定要先关掉ADC,否则读取的数据会中篡位的void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)

{

HAL_ADC_Stop_DMA(AdcHandle);

__NOP();

/* ### - 4 - Start conversion in DMA mode ################################# */

if (HAL_ADC_Start_DMA(AdcHandle,

                        (uint32_t *)aADCxConvertedData,

                        ADC_CONVERTED_DATA_BUFFER_SIZE

                     ) != HAL_OK)

{

    Error_Handler();

}

} 将ADC输入和PWM输出短接 编译、运行然后查看aADCxConvertedData变量的数据 数一下低电平的数量(小于20的数)平均23个左右高电平的数量(大于4080的数)平均24个左右160KHz*(23+24) = 7.52MSPS将AdcHandle.Init.Resolution改为 ADC_RESOLUTION_6B;使用6位模式编译运行,计数高低电平数量平均40个左右160KHz*(40+40)= 12.8MSPS 数据手册中12位的采样率是5.33,6位采样率是8.88,实际采样率怎么会比数据手册还高? 看到数据手册中ADC clock frequency是80MHz,可能是我的例程里使用了120MHz的时钟?如果按照80MHz时钟计算,结果和数据手册接近160KHz*(23+24) = 7.52MSPS/120MHz * 80MHz =5.01MSPS160KHz*(40+40)= 12.8MSPS /120MHz* 80MHz=8.53MSPS难道ADC也能超频?或者是我计算错了? 为了验证我的计算,我在STM32L496ZG的板子上跑了一下相同的例程,12位模式下高低电平的数量分别为17左右,6位模式下高低电平分别为27左右160KHz*(17+17)=5.44MSPS160KHZ*(27+27)=8.64MSPS因为STM32L496主频最高为80MHz,这个结果和数据手册接近
从目前的测试来看,STM32L4R5的ADC主频貌似可以在120MHz时运行不过使用120MHz的ADC时钟时会对测量出来的结果造成多大影响以及是否会对ADC造成不可逆转的损坏还不得而知
下边把两个板子的测试工程放出来,欢迎网友一起来测试

ljj3166 发表于 2018-1-23 12:30

沙发,只要能配置,哪个clock都能oc.
人有多大胆,地有多大产{:1_137:}

our单片机 发表于 2018-1-25 09:54

误差变大了!
页: [1]
查看完整版本: 【NUCLEO-L4R5ZI评测】STM32的ADC原来可以超频?