Einkanal-ADC mit DMA, der auf STM32F7 Müllergebnisse liefert

Ich möchte ADC und DMA mit HAL auf einem F767 implementieren. Ich möchte, dass der ADC immer über DMA konvertiert und im Speicher speichert, bis er die Puffergrenze von 320 erreicht, und dann möchte ich zu einer Callback-Funktion für die vollständige Konvertierung wechseln. ADC scheint gut aktiviert zu sein und konvertiert Werte bis zur Puffergrenze und geht dann zur Konvertierungs-Callback-Routine. Das Problem, das ich habe, ist, wenn ich den ADC-Puffer in der Rückruffunktion für die vollständige Konvertierung überprüfe, dass die erste Hälfte des ADC-Puffers (genau die erste Hälfte, 0 bis 160) mit diesen Werten gefüllt ist, wenn der ADC-Eingang geerdet ist:Geben Sie hier die Bildbeschreibung ein

Ich würde im schlimmsten Fall Werte zwischen 0 und etwa 15 erwarten, also ist es teilweise konsistent.

Wenn ich den ADC an 3 V anschließe, würde ich fast 4096 erwarten, aber stattdessen bekomme ich:

Geben Sie hier die Bildbeschreibung ein

Da die Werte niedriger SIND, wenn der ADC an Masse angeschlossen ist, und höher, wenn der ADC an 3 V angeschlossen ist, handelt es sich nicht um völlige Müllwerte, es handelt sich nicht nur um zufällige Werte, die im Speicher gespeichert sind. Außerdem ist nach der ersten Hälfte des Puffers alles nur Null, also denke ich, dass ich den ADC vielleicht falsch konfiguriert oder falsch gelesen habe. Ich gehe davon aus, dass, weil der DMA die Werte im Array speichert, ich nur das Array während der Konvertierungs-Callback-Funktion überprüfen muss, aber das funktioniert nicht. Die Puffergröße und der DMA-Aufruf

//this code before main #define ADC_BUFFER_LENGTH 340 //5000khz signal / 1.67 Msps = 334 samples

uint32_t ADC_Val[ADC_BUFFER_LENGTH];

//this code after main but before while loop
HAL_ADC_Start_DMA(&hadc1, ADC_Val, ADC_BUFFER_LENGTH);

Und die ADC-Initialisierung:

static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */
//ADC operating @ 1.6MHz - 100MHz/4 = 25MHz
//25MHz/(12+3) = 1.67Msps
  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

und meine Conversion-Callback-Funktion:

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    //chop out sample window 1 and 2
    //sample window 1
    //Pulse Tx is 50 uS wide, there is a settling delay of 20us = 70us
    //with a sampling rate of 1.67Msps 70*1.67 = 119 samples
    uint32_t ADC_SW1_Temp[ADC_SW1_LENGTH] = {0};
    //30us sampled window @ 1.67Msps = 50 samples
    for(int i = 0 ; i < ADC_SW1_LENGTH; i++)
    {
        ADC_SW1_Temp[i] = ADC_Val[(ADC_SW1_START + i)];
    }
    ADC_SW_1 = 0;
}

Ist hier irgendetwas offensichtlich falsch? Wenn nicht, was ist der beste Weg, um das Debugging des DMA und des ADC anzugehen?

Antworten (2)

Es ist kein 32-Bit-ADC, aber Sie interpretieren seine Ausgänge als UINT32.

Betrachten Sie beispielsweise Ihre Leerlaufcodes: 131073 = 2 ( * 2 ** 16) + 1 oder 2 und 1, wenn sie UINT16 gepackt wurden.

Also diese Werte sehen für mich alle gut aus.

Ich könnte dasselbe für die "3V" -Werte tun, aber ich lasse Sie das tun.

riiiiight, und das erklärt, warum genau die zweite Hälfte des Puffers auch leer ist. Ich dachte fälschlicherweise, dass der ADC ein 32-Bit-Datenregister verwendet, und das tut es - nur nicht für einen normalen Einkanalmodus, den ich verwende. Nur die Hälfte wird genutzt und die andere Hälfte ist reserviert. Danke
Ich folge nicht. Warum würde ein vermutlich 12-Bit-ADC zu Werten führen, die größer als 12 Bit sind, nur weil die Daten in einem 32-Bit-Array gespeichert sind? Ist das eine Funktion des DMA?
12 Bits in 32 zu packen wird hässlich. Das Auffüllen auf 16 Bit ist weitaus rationaler und ermöglicht die Kompatibilität zwischen verschiedenen ADCs. Es ist höchstwahrscheinlich eher eine Funktion des ADC-Peripheriegeräts als des ADC: Lesen Sie das Gerätedatenblatt für alle Details.

Sie müssen DMA Continuous Requests aktivieren!

hadc1.Init.DMAContinuousRequests = ENABLE;

Und stellen Sie sicher, dass die Funktion DMA_INIT() vor ADC1_Init() aufgerufen wird