ADC de un solo canal con DMA que da resultados basura en STM32F7

Estoy buscando implementar ADC y DMA con HAL en un F767. Quiero que el ADC siempre convierta y almacene en la memoria a través de DMA hasta que alcance el límite de búfer de 320 y luego quiero ir a una función de devolución de llamada completa de conversión. ADC parece estar bien habilitado y convierte los valores hasta el límite del búfer y luego pasa a la rutina de devolución de llamada de conversión. El problema que tengo es que cuando compruebo el búfer ADC en la función de devolución de llamada de conversión completa es que la primera mitad del búfer ADC (exactamente la primera mitad, 0 a 160) está llena de estos valores cuando la entrada ADC está conectada a tierra:ingrese la descripción de la imagen aquí

Esperaría valores entre 0 y aproximadamente 15 en el peor de los casos, por lo que es parcialmente consistente.

Cuando conecto el ADC a 3V, esperaría cerca de 4096, pero en cambio obtengo:

ingrese la descripción de la imagen aquí

Como los valores SON más bajos cuando el ADC está conectado a tierra y más altos cuando el ADC está conectado a 3V, no son valores completamente basura, no son solo valores aleatorios almacenados en la memoria. Además, después de la primera mitad del búfer, todo son solo ceros, así que estoy pensando que tal vez configuré mal el ADC o lo leí mal. Supongo que debido a que el DMA almacena los valores en la matriz, solo necesito verificar la matriz durante la función de devolución de llamada de conversión, pero esto no funciona. El tamaño del búfer y la llamada DMA

//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);

Y la inicialización del ADC:

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();
  }

y mi función de devolución de llamada de conversión:

    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;
}

¿Hay algo aquí que sea obviamente incorrecto? Si no, ¿cuál es la mejor manera de abordar la depuración de DMA y ADC?

Respuestas (2)

No es un ADC de 32 bits, pero está interpretando sus salidas como UINT32.

Mirando sus códigos inactivos, por ejemplo, 131073 = 2 ( * 2 ** 16) + 1, o 2 y 1 si estaban empaquetados UINT16,

Así que todos esos valores me parecen bien.

Podría hacer lo mismo con los valores de "3V", pero te dejaré hacerlo.

riiiiight, y esto explica por qué exactamente la segunda mitad del búfer también está vacía. Pensé erróneamente que el ADC usaba un registro de datos de 32 bits y lo hace, solo que no para un modo normal de un solo canal que estoy usando. Solo se usa la mitad y la otra mitad se reserva. Gracias
no sigo ¿Por qué un ADC presumiblemente de 12 bits daría como resultado valores superiores a 12 bits solo porque los datos se almacenan en una matriz de 32 bits? ¿Es esa una función de la DMA?
Empaquetar 12 bits en 32 se pone feo. El relleno de 16 bits es mucho más racional y permite la compatibilidad entre diferentes ADC. Lo más probable es que sea una función del periférico ADC en lugar del ADC: lea la hoja de datos del dispositivo para obtener todos los detalles.

¡Debe habilitar las solicitudes continuas de DMA!

hadc1.Init.DMAContinuousRequests = HABILITAR;

Y asegúrese de que la función DMA_INIT() se llame antes que ADC1_Init()