Skip to main content
deep_rune
Associate III
July 6, 2020
Question

how to use ADC in discontinuous mode without HAL?

  • July 6, 2020
  • 0 replies
  • 1422 views

I am trying to use the ADC without using HAL (except for in the setup) on a STM32F031K6, using cubeIDE. Im using the ADC in discontinuous mode - as far as I can tell, the sequence of events should be 

 - ADC is setup, then enabled with ADEN

 - ADC start conversion by setting the ADSTART

 - check the EOC flag to see when the conversion is finished

 - when the data is read from the DR register, the EOC flag is cleared

here's where I'm confused - do I then have to set the ADSTART again? in continuous modes the reference manual seems to indicate the next conversion would automatically take place, but in discontinuos mode states the next conversion needs to be manually started - Im assuming this is done by the ADSTART? In simulation this doesn't seem to work. The datasheet says ADSTART is set by software, does this mean you can't write it directly?

My code is as follows, if I click through step by step it doesn't seem to work properly, if i set it running I can see the ADC1_data variable change as I change the pot on the board, but it works intermittently, changing between 0 and the correct value 

the HAL setup is 

 static void MX_ADC_Init(void)
 {
 ADC_ChannelConfTypeDef sConfig = {0};
 hadc.Instance = ADC1;
 hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc.Init.Resolution = ADC_RESOLUTION_12B;
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc.Init.LowPowerAutoWait = DISABLE;
 hadc.Init.LowPowerAutoPowerOff = DISABLE;
 hadc.Init.ContinuousConvMode = DISABLE;
 hadc.Init.DiscontinuousConvMode = DISABLE;
 hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc.Init.DMAContinuousRequests = DISABLE;
 hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 
 if (HAL_ADC_Init(&hadc) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure for the selected ADC regular channel to be converted. */
 
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Configure for the selected ADC regular channel to be converted. */
 
 sConfig.Channel = ADC_CHANNEL_1;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 }

The code within the program reads 

 ADC1->CR |= ADC_CR_ADEN; // enable ADC
 ADC1 ->SMPR = 0b11;// speed divider select
 ADC1 ->CHSELR |= 1<<0 | 1<<1; // set sequence to adc0, adc1
 ADC1 ->CFGR1 |= ADC_CFGR1_DISCEN; //discontinuous mode
 ADC1 ->CR |= 1<<2; // start conversion
 
 while (1)
 {
	 if((ADC1->ISR) & 0b00000100) //if EOC flag is on
	 {
	 ADC1_data = ADC1->DR; //store data
		 ADC1 ->CR |= 1<<2; // start new conversion
	 }
 }

can anyone confirm if I am making a mistake or not?

any help much appreciated

This topic has been closed for replies.