cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F411 multi-channel DMA + software trigger, VREFINT VBAT two can not collect at the same time

colorhacker
Associate

After using cubemx, I tested the single channel round-robin acquisition and there was no problem.
After changing to DMA acquisition, as long as VREFINT and VBAT exist at the same time, the data of the first channel is wrong. The following is the correct code:

uint16_t data[256]; 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
}
int main{
...
...
while(1){
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)data, hadc1.Init.NbrOfConversion*2);
printf("adc: %d %d %d %d %d %d \n",data[0],data[1],data[2],data[3],data[4],data[5]);
HAL_Delay(1000);
}
}
static void
MX_ADC1_Init(void)
{

/* USER CODE BEGIN ADC1_Init 0 */

/* 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 = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
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 = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
// sConfig.Channel = ADC_CHANNEL_VBAT;
// sConfig.Rank = 2;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
// Error_Handler();
// }

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}
correct result:
adc:1497 378 1497 382 0 0
adc:1497 378 1498 382 0 0
adc:1497 377 1497 381 0 0
adc:1497 378 1498 382 0 0
adc:1497 378 1497 382 0 0

The following is the error code:

 

uint16_t data[256]; 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
}
int main{
...
...
while(1){
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)data, hadc1.Init.NbrOfConversion*2);
printf("adc: %d %d %d %d %d %d \n",data[0],data[1],data[2],data[3],data[4],data[5]);
HAL_Delay(1000);
}
}
static void
MX_ADC1_Init(void)
{

/* USER CODE BEGIN ADC1_Init 0 */

/* 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 = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
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 = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_VBAT;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
// sConfig.Channel = ADC_CHANNEL_0;
// sConfig.Rank = 2;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
// Error_Handler();
// }
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */
}
error result:
adc: 10 919 10 920 0 0
adc: 10 920 10 919 0 0
adc: 11 919 10 920 0 0
adc: 10 919 10 919 0 0
adc: 11 919 10 919 0 0
adc: 11 919 9 919 0 0
adc: 11 920 10 919 0 0


The only difference above is whether Vbat and channel 0 are turned on or not. I have no idea why the number of the first channel is around 10. I tested it for a long time and finally found the smallest error code. Please help me check it. Thank you.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

You cannot measure both VREFINT and VBAT in one go.

Thing is, for some weird reason, VBAT and TEMP measuremets are connected to a single input ADC1_IN18 (*); and, for another weird reason, the switch which toggles between VBAT and TEMP (ADC_CCR.TSVREFE) also switches off VREFINT.

(*) RM0383 mentions that TEMP is connected also to ADC1_IN16 but still, ADC_CCR.TSVREFE either allows VBAT or VREFINT measurement, not both.

Btw. don't forget to switch off VBAT measurement after taking the measurement, to avoid discharging the battery.

JW

View solution in original post

2 REPLIES 2

You cannot measure both VREFINT and VBAT in one go.

Thing is, for some weird reason, VBAT and TEMP measuremets are connected to a single input ADC1_IN18 (*); and, for another weird reason, the switch which toggles between VBAT and TEMP (ADC_CCR.TSVREFE) also switches off VREFINT.

(*) RM0383 mentions that TEMP is connected also to ADC1_IN16 but still, ADC_CCR.TSVREFE either allows VBAT or VREFINT measurement, not both.

Btw. don't forget to switch off VBAT measurement after taking the measurement, to avoid discharging the battery.

JW

thank you so much!