Así que he buscado por todas partes una solución a este problema, pero puedo encontrar cualquier cosa. Tengo tres canales conectados a ADC1
de mi STM32F446ZE-nucleo y quiero muestrear los canales a una frecuencia de 200 Hz cada uno. Configuré TIM2
y lo vinculé como la interrupción para la conversión de ADC, y esto funciona bien para 1 canal. Pero estoy luchando para que funcione para varios canales, ya que no sé cómo obtener los datos de cada canal específico dentro de HAL_ADC_ConvCpltCallback
.
Mi configuración se ve así:
/* ADC1 init function */
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**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 = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = 3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 41999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 4;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
Comienzo mi ADC
y el temporizador después de recibir datos en USART3
así:
// start timer and ADC interrupt
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim2);
Aquí es donde estoy luchando para obtener los datos correctos:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
// get values
WE_ADC_VAL = HAL_ADC_GetValue(hadc);
uint32_t nrConv = hadc->NbrOfCurrentConversionRank;
// populate buffer
transmitBuf[0] = WE_ADC_VAL >> 8; // upper 8 bits
transmitBuf[1] = WE_ADC_VAL & 0x00FF; // lower 8 bits
// send by interrupt mode
HAL_UART_Transmit_IT(&huart3, transmitBuf, 2);
}
Pensé que hadc->NbrOfCurrentConversionRank
debería tener información sobre qué canal se está muestreando, pero es constantemente 0 (pensé que iría de 1 a 2 a 3). ¿Cómo hago para obtener los datos del canal individual en cada interrupción de conversión completa? Cualquier ayuda sería apreciada :)