Me enfrento a un problema relacionado con la adquisición continua del canal ADC en STM32F103.
Uso la interrupción al final de la conversión para llamar a una función de devolución de llamada para almacenar el valor adquirido.
El problema se refiere a la devolución de llamada que se llama solo la primera vez.
Configuré mi proyecto usando STM32CubeMx para adquisición continua y generación de interrupciones.
Esta es la configuración del ADC:
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/**Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Esta es mi función de adquisición:
ea_ADC_Err_Code_t ea_ADC_n_data_read(Adc_Channel_t channel, adc_eoc_callback adc_cb)
{
ea_ADC_Err_Code_t err_code = ADC_ERR;
ADC_ChannelConfTypeDef sConfig;
adc_read_value = 0;
adc_eoc_cb = adc_cb;
n_adc_acquisition = ADC_MAX_CONS_ACQ;
/* Deinit ADC */
//while(HAL_ADC_DeInit(&adc_handler) != HAL_OK);
/* Initialize ADC */
//HAL_ADC_Init(&adc_handler);
/* Configure ADC Channel */
sConfig.Channel = channel;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&adc_handler, &sConfig);
/* Set ADC callback */
HAL_ADC_ConvCpltCallback(&adc_handler);
/* ADC Calibration */
//HAL_ADCEx_Calibration_Start(&adc_handler);
/* Start conversion with interrupt*/
if (HAL_ADC_Start_IT(&adc_handler) == HAL_OK)
{
err_code = ADC_OK;
}
return err_code;
}
Y finalmente mi devolución de llamada:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (n_adc_acquisition)
{
adc_read_value += HAL_ADC_GetValue(&adc_handler);
n_adc_acquisition--;
edi_Print_L1("ADC Callback %d\n", n_adc_acquisition);
}
else
{
HAL_ADC_Stop_IT(&adc_handler);
adc_read_value = adc_read_value >> ADC_DIVIDE_BY_EIGTH;
adc_eoc_cb(adc_read_value);
}
}
¿Olvidé algo en la devolución de llamada?
Se olvidó de habilitar las interrupciones ADC, que se puede hacer algo como esto:
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
Lo siguiente con el manejo de interrupciones de HAL es que hay dos declaraciones de funciones débiles.
void ADC_IRQHandler()
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
Debe implementar el ADC_IRQHandler()
primero, se llamará cuando el ADC genere una interrupción. Dentro de esta función, debe llamar al HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
parámetro , es el controlador de su ADC ( ADC_HandleTypeDef
).
void ADC_IRQHandler()
{
HAL_ADC_IRQHandler(&hadc1);
//HAL_ADC_IRQHandler(&hadc2); <--- In case of a second ADC
}
Ahora, HAL_ADC_IRQHandler()
verificará cada tipo de error por usted (puede verificarlo en su implementación) y si todo está bien, llamará al void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
. Como también tiene una declaración débil, debe implementar la función.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
int converted_value = HAL_ADC_GetValue(hadc);
// Do stuff
}
//if(hadc->Instance == ADC2) // <-- In case of a second ADC
//{
//
//}
}
En STM32CubeMX, en la ventana Configuración de ADC1, hay una pestaña llamada Configuración de NVIC . Aquí puede habilitar las interrupciones globales para ADC1 y ADC2, y si lo hace, STM32Cube las implementará void ADC_IRQHandler(void)
en el archivo stm32f1xx_it.c .
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles ADC1 and ADC2 global interrupts.
*/
void ADC_IRQHandler(void)
{
/* USER CODE BEGIN ADC_IRQn 0 */
/* USER CODE END ADC_IRQn 0 */
HAL_ADC_IRQHandler(&hadc1);
/* USER CODE BEGIN ADC_IRQn 1 */
/* USER CODE END ADC_IRQn 1 */
}
También es solo un breve resumen, por lo que sugiero leer el tutorial que @Eugene Sh le mostró.
Eugenio Sh.
federico
Eugenio Sh.
Eugenio Sh.
HAL_ADC_ConvCpltCallback
para que vea que se llama.Marko Bursic
federico
Eugenio Sh.
Marko Bursic
Eugenio Sh.
federico
Eugenio Sh.
federico
Eugenio Sh.
HAL_ADC_ConvCpltCallback(&adc_handler);
esta línea está llamando a la función.Eugenio Sh.
main
, ya que el flujo no está claro.federico
Eugenio Sh.