1

I am using a STM32H723ZG board for a project. In this project I must sample the signal coming from an image sensor that sends the pixel values as pulses with analog amplitudes. This sensor also provides a trigger signal so that the pixels data should be sampled at the rising edge of the trigger signal (an example is shown in the image below).

enter image description here

T_SAR (sampling time in terms of ADC clock) and T_SMPL (conversion time in terms of ADC clock) define how long the sampling and conversion process takes. Based on the application note How to get the best ADC accuracy in STM32 microcontrollers, it is difficult to estimate the Sampling Time for the ADC in order to fill completely the internal capacitors. So I used the SAR stimation tool (shown in the page 37 of the mentioned application note) to estimate that 8.5 adc cycles were necessary for the sampling operation for a 16- bit ADC with a resolution of 12 bits in fast channel (the board that I am using doesn't have direct channels for those ADCs).

Based on the following table (available in the pg.1014 in the reference manual RM0468):

enter image description here

The T_SAR = 6.5 ADC clocks and the sampling time T_SMPL = 8.5 ADC clocks. so the total time for a sampling and conversion operation is 15 ADC clocks. The ADC frequnecy clock is 50 MHz, so the total time would be: 15 ADC clocks = 300 ns. In other words, in continuous mode, the sampling and conversion frequency would be 3,33 MHz.

The pixel pulses are sent with a frequency of 5 Mhz. For that reason I decided to use the two 16-bit ADCs with 12 bits resolution in alternate trigger mode. In this mode, both ADCs are triggered by an external signal alternately. So, in this way, I can read the signal at 5MHz.

The alternate trigger mode can only be implemented with injected channels (mentioned in the reference manual), which eliminates the possibility of using the DMA because DMA doesn't work with injected channels. So, I am using the ADCs with polling.

I am also calibrating the ADCs independently before starting them. However, there is a strange behaviour in the sampled signal after uploading the code. When I upload the code, I randomly get any of three possible outcomes:

enter image description here

Every time I upload the code to the board, one of the three results (shown above) appears and it does not change over time. The signal that I would like to get all the time is the first one (clause a)). Does anyone know why is this happening and how I could fix it? At the beginning, I though that the internal ADC capacitors were not full so it could be a source of error. So I did what I explained before. Then, I though it was because there wasn't enough waiting time for the initialization of the peripherals, but I already tried putting delays of 10 ms after the calibration and initialization of the ADCs (before they start sampling) and the results are still the same.

My configurations for the ADCs are: For the ADC1:

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_DUALMODE_ALTERTRIG;
  multimode.DualModeData = ADC_DUALMODEDATAFORMAT_DISABLED;
  multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Disable Injected Queue
  */
  HAL_ADCEx_DisableInjectedQueue(&hadc1);

  /** Configure Injected Channel
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_4;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_8CYCLES_5;
  sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
  sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
  sConfigInjected.InjectedOffset = 0;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.QueueInjectedContext = DISABLE;
  sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_EXT_IT15;
  sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
  sConfigInjected.InjecOversamplingMode = DISABLE;

For the ADC2:

  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc2.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Disable Injected Queue
  */
  HAL_ADCEx_DisableInjectedQueue(&hadc2);

  /** Configure Injected Channel
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_4;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_8CYCLES_5;
  sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
  sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
  sConfigInjected.InjectedOffset = 0;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.QueueInjectedContext = DISABLE;
  sConfigInjected.InjecOversamplingMode = DISABLE;
Carlos T
  • 33
  • 4
  • The worst SNR looks like 16:1 or 0000..10000 if that means anything. Try a triangle calibration signal and compare error levels. – Hoagie Feb 27 '23 at 22:46

0 Answers0