cancel
Showing results for 
Search instead for 
Did you mean: 

STM32C031C6T6 Multi channel ADC not working

RChou.1
Associate III

Hello All, I am working on a raw STM32C031C6T6 directly soldered on a breakout board and trying to make a multi channel interrupt based ADC working but the problem i am facing is all the adc's are giving me the same values even after setting the separate channel for individuals and when i decided to use dma it stuck when continue dma request is enable  and when its not dma just reads a single cycle.

below i have  provided you the screenshot of my configuration and clock settings i have used as well as i am attaching my code which i have made for this.

any kind of help will be really appreciable.    

 

 

 

IMG-20240302-WA0000.jpgIMG-20240302-WA0001.jpg

 

 

IMG-20240302-WA0002.jpg

 

 

 

 

 

 

__IO uint16_t counter=0,secCounter=0;
 uint32_t uADCVal[4];
__IO uint8_t ADCflag=0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){

	if (htim->Instance == TIM3) {
		counter++;
		if (counter >= 500) {

			counter=0;
			secCounter++;
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
	}
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hadc);

  /* NOTE : This function should not be modified. When the callback is needed,
            function HAL_ADC_ConvCpltCallback must be implemented in the user file.
   */
  ADCflag=1;
}

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

/* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim3);
  HAL_ADC_Start_IT(&hadc1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	if (ADCflag) {
		for (int var = 0; var < 4; var++) {
		  uADCVal[var] = HAL_ADC_GetValue(&hadc1);
		}
		ADCflag=0;
		//HAL_ADC_Start_IT(&hadc1);
	}
  }
  /* USER CODE END 3 */
}

 

 

 

 

 

8 REPLIES 8
MM..1
Chief III

Have you scan mode enabled ? Better as photo is attach ioc file or show code adc init...

And 1,5 cycle ...

Do you know that the ADC has multiple channels and these have to be configured as "RANK"s?

How many RANKs are configured in your system? I would guess: the CubeMX tool does not configure multiple channels, just the main ADC setup.

On my STM32U5A5 project, I "need" this:

  /** Configure Regular Channel */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_68CYCLES;	//ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    //Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_VBAT;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    //Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    //Error_Handler();
  }

  HAL_ADCEx_Calibration_Start(&hadc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);

 

TDK
Guru
		for (int var = 0; var < 4; var++) {
		  uADCVal[var] = HAL_ADC_GetValue(&hadc1);
		}

This is not how the ADC works. It does not store the values for all channels in a buffer which you can read out later.

Use DMA to convert multiple channels.

If you feel a post has answered your question, please click "Accept as Solution".
RChou.1
Associate III

Then how can i read multiple channel using ADC interrupt when End of Sequence conversion happens.

This example is based on some tutorial on youtube. 

For your reference I'm attaching my ioc file and hoping for your reply.

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_DIV2;
  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.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 3;
  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.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

here is my adc init as well as i have attached my ioc file with this.

Above on Mr MM..1's post i have attached my ioc file and if you could check them once for any error would be really appreciable.

And if you could provide me any sample code using Multichannel ADC interrupt mode can help me a lot to understand better.

Using DMA would be the supported solution. You can use interrupts if your code is fast enough. The reference manual provides instructions on how to set this up. You probably won't find examples of it as it's prone to overrun errors.

 

TDK_0-1709560104792.png

 

If you feel a post has answered your question, please click "Accept as Solution".

SamplingTime common 1 set to value around 100 cycles and use common 1 on channels...

29 (youtube.com)