TIMER triggered DMA - AD conversion, STM32F4 works only ones

0

I am implementing an a/d conversion with DMA transfer fired by a timer on a nucleo-STM32F401RE board. Both TIMER2, the one used for the time base, and ADC with DMA looking at the debug are fine. But when I use the timer to start the AD conversion it works only once, and then the timer go on, but don't starts the ADC.

I cannot find if there is some flag to clear or set. Here the code:

TIMER 2 (changed sMasterConfig.MasterOutputTrigger from TIM_TRGO_RESET to TIM_TRGO_UPDATE, else ADC never starts):

void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 100;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;  //TIM_TRGO_RESET
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

ADC (if I set DMA continuos request at the end of one burst starts immediatly another and ignore the timer):

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_8B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

}

MAIN and CallBack:

#define DEBUG 1
#define UART_RX_BUF_SIZE 1
#define UART_TIMEOUT 0X00000FFF
#define ADC_BUF_SIZE 10

volatile uint8_t UART_rx_buf[UART_RX_BUF_SIZE] = {0};
volatile uint8_t UART_rx_pending = 0;
const volatile char UART_tx_start[1] = "U";
volatile uint8_t UART_timeout = 0;

volatile uint16_t ADC_buf[ADC_BUF_SIZE] = {0};

int main(void)
{
  HAL_Init();

  SystemClock_Config();
  
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();

#ifdef DEBUG
  DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP;
#endif

  /*INITIALIZATION: SEND A CHARACTER AND WAIT FOR A RESPONSE*/
  HAL_Delay(10);
  UART_timeout = HAL_UART_Transmit(&huart2, (uint8_t*)UART_tx_start, (uint16_t)1, (uint32_t)UART_TIMEOUT);
  UART_timeout = HAL_UART_Receive(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE, (uint32_t)UART_TIMEOUT);
      if(UART_timeout == HAL_TIMEOUT)  UART_config_timeout();

  /*START CONFIGURATION*/
  TIMER_CONFIG(UART_rx_buf[0]);     //SET TIMER PRSC AND ARR

  HAL_UART_Receive_IT(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE);  //UART RX INTERUPT ENABLE
  TIM2 -> EGR |= 0x00000001;    //RESET TIMER
  HAL_TIM_Base_Start(&htim2);   //START TIMER
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADC_buf, ADC_BUF_SIZE);     //START ADC-DMA REQUEAST

  while (1)
  {
      if(UART_rx_pending == 1)  {

            UART_rx_pending = 0;
            /*MANAGE RX DATA*/
            HAL_UART_Receive_IT(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE);
      }
  }
}

=============================================================================================

void HAL_UART_RxCpltCallback (UART_HandleTypeDef* huart)  {UART_rx_pending = 1;}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)  {}

The first part of the main perform a short data transfer with the pc to set the ARR and PSC of TIMER2, in debug their values are fixed, and EGR is masked in order to reset the timer with the new values of ARR and PSC.

There is something that I miss?

timer
stm32
microcontroller
dma
adc
asked on Stack Overflow Nov 19, 2020 by Christian Conti

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0