STM32 HAL_ADC_Start() termina con HAL_ERROR

Soy nuevo en la programación de microcontroladores y tengo un problema que no puedo resolver.

Estoy usando la placa STM32 Nucleo L4R5ZI y trato de leer el valor analógico en uno de los pines, y luego uso el ADC para convertirlo y enviarlo a la PC usando el UART.

Pero cuando uso este código, solo obtengo un "0" en mi PC. Parece que la HAL_ADC_start()función regresa HAL_ERROR. ¿Sabes lo que podría ser?

Espero que lo entiendas, el inglés no es mi idioma nativo :)

ADC_HandleTypeDef hadc1;
UART_HandleTypeDef hlpuart1;

...

uint16_t raw;
char msg[10];

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();
MX_LPUART1_UART_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_ADC1_Init();


    while (1){
    
      HAL_ADC_Start(&hadc1);
      HAL_ADC_PollForConversion(&hadc1, 100);
      raw = HAL_ADC_GetValue(&hadc1);
      sprintf(msg, "%hu\r\n", raw);

      HAL_UART_Transmit(&hlpuart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
      HAL_Delay(5);
    }

...

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;

EDITAR 1
Descubro que HAL_ADC_startla función regresa HAL_ERRORen esta sección del código:

while (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
    {
      /*  If ADEN bit is set less than 4 ADC clock cycles after the ADCAL bit
          has been cleared (after a calibration), ADEN bit is reset by the
          calibration logic.
          The workaround is to continue setting ADEN until ADRDY is becomes 1.
          Additionally, ADC_ENABLE_TIMEOUT is defined to encompass this
          4 ADC clock cycle duration */
      /* Note: Test of ADC enabled required due to hardware constraint to     */
      /*       not enable ADC if already enabled.                             */
      if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
      {
        LL_ADC_Enable(hadc->Instance);
      }

      if ((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
      {
        /* Update ADC state machine to error */
        SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);

        /* Set ADC error code to ADC peripheral internal error */
        SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);

        return HAL_ERROR;
      }
    }
return HAL_OK;

Es parte de la función ADC_Enable()que se usa en HAL_ADC_start(). La condición en while()todavía TRUEsignifica que se produce un tiempo de espera más tarde.

Aun no se como solucionarlo.

Puede depurar la HAL_ADC_Startfunción para verificar la condición que hace que regrese HAL_ERROR.
Esto suele ser el resultado de alguna pieza de inicialización faltante o un intento de elección de opción no válido. Vea si hay un ejemplo de fabricante que pueda ejecutar primero sin modificar.
¿Tenemos una solución al final? Estoy enfrentando un problema similar en mi extremo con STM32U5.

Respuestas (1)

Algunas cosas que podrías probar:

  1. Verifique que el reloj para el ADC esté habilitado; por lo tanto, en la SystemClock_Config()función busque la línea que establece PeriphClkInit.PeriphClockSelectiony asegúrese de que contenga RCC_PERIPHCLK_ADC.

  2. Verifique que la frecuencia del reloj para el ADC sea aceptable: use STM32CubeMX y mire la pestaña "Configuración del reloj" y asegúrese de que no arroje ningún error.

  3. Su código está ejecutando el ADC como un solo uso, pero lo está configurando para un muestreo continuo hadc1.Init.ContinuousConvMode = ENABLE;. Puede valer la pena configurar esto DISABLEen su lugar.


Respuesta anterior dejada aquí para la posteridad:

Estoy viendo el mismo problema (HAL_ADC_Start() devolviendo HAL_ERROR), aunque con una compilación PlaformIO + STM32CubeMX. En este caso, PlatformIO compila el código CMSIS y el código del controlador CubeMX HAL por separado en dos bibliotecas: libFrameworkCMSISDevice.a y libFrameworkHALDriver.a.

En la biblioteca libFrameworkHALDriver existe una serie de funciones que se definen dos veces, una con enlace débil y la segunda con enlace fuerte.

Para mí, el enlace final produce una salida que solo tiene la versión débil de muchas de estas funciones. Para la función HAL_ADC_Start() en cuestión, solo tiene la versión débil, que no hace nada y devuelve HAL_ERROR, que es el síntoma informado en la pregunta.

Mirando esto un poco más, parece que al vincular bibliotecas estáticas, el vinculador no anula los símbolos débiles que se ven al principio del enlace con los fuertes que se ven más tarde. Por ejemplo, vea esta discusión: https://stackoverflow.com/a/37191811/1770902 .

Por lo tanto, si esto es lo que está causando su problema, la solución parecería ser colocar los archivos con los símbolos fuertes antes en el enlace que los símbolos débiles que deberían anular.

En mi caso, aún no he descubierto cómo solucionar este problema, ya que no parece haber ninguna forma de influir en el orden en que las compilaciones de la biblioteca PlatformIO han incluido los archivos de objetos.

La "biblioteca" hal generalmente se compila como parte de un proyecto, no se precompila en una biblioteca estática y se vincula, por lo que el mecanismo de la biblioteca normalmente no se utiliza para esto. Los archivos .o que se muestran aquí no son "bibliotecas"
Tal vez mi respuesta brinde mensajes mixtos, pero en mi caso de usar PlatformIO con STM32CubeMX para compilar la placa STM32F323C-EVAL crea dos bibliotecas estáticas, con las que se vincula automáticamente. Estos son libFrameworkCMSISDevice.a y libFrameworkHALDriver.a. En libFrameworkHALDriver.a, la función HAL_ADC_Start() aparece dos veces, la primera es una versión débil y la segunda fuerte. En la salida final enlazada solo existe la versión débil.
Actualicé mi respuesta para brindar más información sobre la situación en la que tengo un problema con los mismos síntomas.
Eso parecería ser distinto de esta pregunta.
Sí, acepto que puede ser. Pero también puede que no lo sea, ya que el OP no especifica cuál es su configuración. Si está usando PlatformIO con STM32CubeMX para obtener su configuración de HAL, entonces mi respuesta sería pertinente para su caso. De lo contrario, esto puede ayudar a que alguien más esté usando PlatformIO con STM32CubeMX que responda a esta pregunta, como lo hice yo, buscando por qué veo que HAL_ADC_Start() falla con HAL_ERROR.
Las "respuestas" aquí deben abordar específicamente la pregunta realmente formulada, las conjeturas descabelladas que incorporan errores en su propia explicación y no tienen evidencia de respaldo en la pregunta en sí realmente no son beneficiosas para el sitio y tienden a conducir solo a "intente esto" desinformado. ismo. La cosa de la que estás hablando ya tiene una pregunta propia aquí.
Bien, entonces diría que la pregunta que realmente se hace es "¿por qué HAL_ADC_Start() devuelve HAL_ERROR"?