cancel
Showing results for 
Search instead for 
Did you mean: 

ADC problems

tompa
Associate III

Hi, 

I am having a strange ADC problem on my STM32L431 device. I am sampling 6 channels without DMA using polling method with the following code:

 

 

while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ ADC_Select_CH0(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[0] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); ADC_Select_CH1(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[1] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); ADC_Select_CH2(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[2] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); ADC_Select_CH3(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[3] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); ADC_Select_CH4(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[4] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); ADC_Select_CH5(); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_values[5] = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); HAL_Delay(100); printf("IN 4 = H1:21 = %d\n\r",adc_values[0]); printf("IN 9 = H2:7 = %d\n\r",adc_values[1]); printf("IN 13 = H2:15 = %d\n\r",adc_values[2]); printf("IN 14 = H2:17 = %d\n\r",adc_values[3]); printf("IN 15 = H2:19 = %d\n\r",adc_values[4]); printf("IN 16 = H2:21 = %d\n\r",adc_values[5]); printf("\nFinished ADC Conversion for all channels\r\n"); HAL_Delay(2000); }
View more

 

 

only IN 16 shows 0 and 4095 when connected to GND and Vdd. All other channels showing unexpected values - around 3500 for Vdd and around 1500 for GND. What could be a problem ? ADC_Select functions are these - always rank 1:

 

 

void ADC_Select_CH0 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_4; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { printf("govance"); Error_Handler(); } } void ADC_Select_CH1 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_9; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void ADC_Select_CH2 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_13; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void ADC_Select_CH3 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_14; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void ADC_Select_CH4 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_15; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void ADC_Select_CH5 (void) { ADC_ChannelConfTypeDef sConfig = {0}; /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_16; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } }
View more

 

 

 My ADC Init function is here:

 

 

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 */ /** Common config */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.NbrOfConversion = 6; hadc1.Init.DiscontinuousConvMode = DISABLE; 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; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ // sConfig.Channel = ADC_CHANNEL_4; // sConfig.Rank = ADC_REGULAR_RANK_1; // sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; // sConfig.SingleDiff = ADC_SINGLE_ENDED; // sConfig.OffsetNumber = ADC_OFFSET_NONE; // sConfig.Offset = 0; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } // // /** Configure Regular Channel // */ // sConfig.Channel = ADC_CHANNEL_9; // sConfig.Rank = ADC_REGULAR_RANK_2; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } // // /** Configure Regular Channel // */ // sConfig.Channel = ADC_CHANNEL_13; // sConfig.Rank = ADC_REGULAR_RANK_3; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } // // /** Configure Regular Channel // */ // sConfig.Channel = ADC_CHANNEL_14; // sConfig.Rank = ADC_REGULAR_RANK_4; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } // // /** Configure Regular Channel // */ // sConfig.Channel = ADC_CHANNEL_15; // sConfig.Rank = ADC_REGULAR_RANK_5; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } // // /** Configure Regular Channel // */ // sConfig.Channel = ADC_CHANNEL_16; // sConfig.Rank = ADC_REGULAR_RANK_6; // if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) // { // Error_Handler(); // } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ }
View more

 

 

 Any advice is really appreciated, thank you very much!

1 ACCEPTED SOLUTION

Accepted Solutions

Thank you very much for your replay,

Yes, I changed my code to this:

 

void ADC_Select_Channel(uint32_t channel, uint16_t *result) { ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = channel; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } uint32_t sum = 0; for (int i = 0; i < 3; i++) { HAL_ADC_Start(&hadc1); if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) { sum += HAL_ADC_GetValue(&hadc1); } else { printf("ADC Polling Error on channel %lu\r\n", channel); Error_Handler(); } HAL_ADC_Stop(&hadc1); //HAL_Delay(10); // Pauza između mjerenja } *result = sum / 3; // Spremi srednju vrijednost } void Measure_All_Channels(void) { uint16_t result_CH0, result_CH1, result_CH2, result_CH3, result_CH4, result_CH5, result_CH6; ADC_Select_Channel(ADC_CHANNEL_4, &result_CH0); printf("Channel 0 Average Value: %u\r\n", result_CH0); ADC_Select_Channel(ADC_CHANNEL_9, &result_CH1); printf("Channel 1 Average Value: %u\r\n", result_CH1); ADC_Select_Channel(ADC_CHANNEL_13, &result_CH2); printf("Channel 2 Average Value: %u\r\n", result_CH2); ADC_Select_Channel(ADC_CHANNEL_14, &result_CH3); printf("Channel 3 Average Value: %u\r\n", result_CH3); ADC_Select_Channel(ADC_CHANNEL_15, &result_CH4); printf("Channel 4 Average Value: %u\r\n", result_CH4); ADC_Select_Channel(ADC_CHANNEL_16, &result_CH5); printf("Channel 5 Average Value: %u\r\n", result_CH5); printf("------------------------\n"); }
View more

and it works OK in this most simplistic way. I tried also a Scan Conversion Mode but I didn't succeed.
And with DMA usage my main loop stops to iterate... 

View solution in original post

5 REPLIES 5
Karl Yamashita
Principal

You don't check the HAL status when you call HAL_ADC_PollForConversion. So how do you know if it return HAL_OK, HAL_ERROR or HAL_TIMEOUT?

 

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.
waclawek.jan
Super User

What hardware is this, your own or a "known good" board like Nucleo or Disco?

How exactly are you "connecting the pins to GND or VCC", via a resistor or directly?

Read out and check/compare-to-working/post ADC and relevant GPIO registers content.

JW

Thank you very much for your replay,

Yes, I changed my code to this:

 

void ADC_Select_Channel(uint32_t channel, uint16_t *result) { ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = channel; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } uint32_t sum = 0; for (int i = 0; i < 3; i++) { HAL_ADC_Start(&hadc1); if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) { sum += HAL_ADC_GetValue(&hadc1); } else { printf("ADC Polling Error on channel %lu\r\n", channel); Error_Handler(); } HAL_ADC_Stop(&hadc1); //HAL_Delay(10); // Pauza između mjerenja } *result = sum / 3; // Spremi srednju vrijednost } void Measure_All_Channels(void) { uint16_t result_CH0, result_CH1, result_CH2, result_CH3, result_CH4, result_CH5, result_CH6; ADC_Select_Channel(ADC_CHANNEL_4, &result_CH0); printf("Channel 0 Average Value: %u\r\n", result_CH0); ADC_Select_Channel(ADC_CHANNEL_9, &result_CH1); printf("Channel 1 Average Value: %u\r\n", result_CH1); ADC_Select_Channel(ADC_CHANNEL_13, &result_CH2); printf("Channel 2 Average Value: %u\r\n", result_CH2); ADC_Select_Channel(ADC_CHANNEL_14, &result_CH3); printf("Channel 3 Average Value: %u\r\n", result_CH3); ADC_Select_Channel(ADC_CHANNEL_15, &result_CH4); printf("Channel 4 Average Value: %u\r\n", result_CH4); ADC_Select_Channel(ADC_CHANNEL_16, &result_CH5); printf("Channel 5 Average Value: %u\r\n", result_CH5); printf("------------------------\n"); }
View more

and it works OK in this most simplistic way. I tried also a Scan Conversion Mode but I didn't succeed.
And with DMA usage my main loop stops to iterate... 

Thank you very much for your reply!

I finally made it with the code I posted in earlier reply.

I use my own board and connecting pins to GND and VCC directly - but it works ok now except Scan Conversion Mode. I obviously don't know how to do it... More studying to come. 

Hello @tompa 

For the scan mode you can refer to this LL example on STM32F411-Nucleo board.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om