5
votes

I am trying to configure ADC over a STM32F411RE in simple Continuous Conv Mode. I used CubeMX to generate the code based on HAL drivers and this is some parts of the generated code which intialize ADC:

/* ADC1 init function */
void MX_ADC1_Init(void)
{

    /**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_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_8B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  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 = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

}

and here is the main function:

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();

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  /* USER CODE BEGIN 2 */
  uint8_t analogVal;
  uint8_t string[] = "Poll failed\n";

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  HAL_Delay(1000);
  if( HAL_ADC_Start(&hadc1) == HAL_OK) HAL_UART_Transmit(&huart2,(uint8_t*)"STRT OK\n",8,100);
  else HAL_UART_Transmit(&huart2,(uint8_t *)HAL_ADC_Start(&hadc1),1,100);
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    if(HAL_ADC_PollForConversion(&hadc1,1) == HAL_OK){
      analogVal = HAL_ADC_GetValue(&hadc1);
      HAL_UART_Transmit(&huart2,&analogVal,sizeof(analogVal),100);
    }
    else{
      HAL_UART_Transmit(&huart2,string,sizeof(string)-1,100);
    }
    HAL_Delay(100);
  }
  /* USER CODE END 3 */

}

If I compile and upload this code into the microcontroller, no more than once analogVal would be transmitted over UART. But if I place HAL_ADC_Start function inside the while loop, HAL_ADC_PollForConversion returned value will be HAL_OK in every cycle of while and there will be a analogVal to report.

My question is, why should I everytime ask the ADC to start if I have enabled ContinuousConvMode?

2

2 Answers

9
votes

I am sure that the EOC flag setting is the problem. hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; should be changed to hadc1.Init.EOCSelection = EOC_SEQ_CONV;.

Your current option ADC_EOC_SINGLE_CONV acts like an enable of single conversion, but you need EOC_SEQ_CONV aka sequential conversions.

It is pretty much the same problem that has been discussed here.

0
votes

According to reference manual (RM0383, p. 214):

The Scan mode is selected by setting the SCAN bit in the ADC_CR1 register. Once this bit has been set, the ADC scans all the channels selected in the ADC_SQRx registers (for regular channels) or in the ADC_JSQR register (for injected channels). A single conversion is performed for each channel of the group. After each end of conversion, the next channel in the group is converted automatically. If the CONT bit is set, regular channel conversion does not stop at the last selected channel in the group but continues again from the first selected channel.

So additionaly you have to declare group of channels and amount of them in ADC_SQR register (in your case it will be only one channel).

EDIT: Please note that in your example which you posted there is external triggering of each conversion by Timer:

 g_AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;

But right I haven't seen initialization of timer in the rest of this code.