¿Cómo leer de múltiples canales del ADC en un STM32F407?

1

Estoy trabajando en un proyecto en el que necesito leer las salidas analógicas de 4 fuentes y convertirlas a un valor digital usando un solo módulo ADC en el microcontrolador STM32F407. Quiero muestrear los valores de ADC cada 50 ms y, por lo tanto, he decidido usarlos en el modo de sondeo y tener un temporizador de interrupción cada 50 ms para activar la lectura de ADC. Estoy usando el software STM32 CubeMX para generar inicializaciones para mí.

Aquí están las inicializaciones de ADC:

hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.NbrOfDiscConversion = 0;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = DISABLE;

Y en mi función principal:

while (1)
{
/* USER CODE END WHILE */
g_ADCValue = HAL_ADC_GetValue(&hadc1);
}

Ahora esto funciona cuando tengo un canal ADC habilitado, pero ¿cómo leo de más de 1 canal al mismo tiempo? ¿Cómo la función GetValue() devuelve el valor ADC de un determinado canal? También sé que no quiero usar interrupciones de ADC para esto, ya que quiero muestrear el ADC en intervalos de tiempo particulares (cada 50 ms), pero ¿debo usar DMA? Si es así, ¿cómo haría eso?

¡Muchas gracias por toda tu ayuda!

    
pregunta Shubham Rastogi

2 respuestas

1
hadc1.Init.ScanConvMode = DISABLE;

el secuenciador está deshabilitado por lo que no puede leer o incluso convertir los datos provenientes del otro canal.
También tienes que definir el rango de cada canal.
por ejemplo:

sConfig.Rank      = 1;
     sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5 ;
     sConfig.Channel = REF_1_5_Volt_Pin;
     HAL_ADC_ConfigChannel(&hadc, &sConfig);
 sConfig.Rank = 2;
 sConfig.Channel = L1_voltage_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);

 sConfig.Rank = 3;
 sConfig.Channel = L2_voltage_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);

 sConfig.Rank = 4;
 sConfig.Channel = L3_voltage_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);

 sConfig.Rank = 5;
 sConfig.Channel = L1_curent_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);

 sConfig.Rank = 6;
 sConfig.Channel = L2_curent_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig);

 sConfig.Rank = 7
 sConfig.Channel = L3_curent_Pin;
 HAL_ADC_ConfigChannel(&hadc, &sConfig)
    
respondido por el Aymen Lachkhem
0
  

Quiero muestrear los valores de ADC cada 50 ms

     

hadc1.Init.ContinuousConvMode = ENABLE;

Supongo que necesitas convertir todos los canales solo una vez en 50 ms, lo que significa que debes desactivar la conversión continua porque reiniciará la conversión automáticamente sin esperar a que se active el disparo de 50 ms.

  

hadc1.Init.DMAContinuousRequests = ENABLE;

Esto permitirá que el canal DMA recopile datos convertidos del registro de datos de ADC y se transferirá a cualquier ubicación de RAM.

Según lo sugerido por @Aymen Lachkhem, debe configurar el rango para cada canal, esto agregará los canales deseados al secuenciador para la conversión; de lo contrario, ese canal en particular no se escaneará.

Sugerencia: puede iniciar la conversión de ADC utilizando DMA, proporcionar la ubicación de RAM y la cantidad de datos que se transferirán. Puede recopilar datos convertidos cuando se invoca la devolución de llamada completa de DMA. La biblioteca HAL proporciona API para iniciar la conversión de ADC utilizando DMA y una implementación débil de devolución de llamada.

    
respondido por el Chandan Kumar

Lea otras preguntas en las etiquetas