Skip to main content
dming.4
Associate II
July 22, 2022
Question

When to stop TIM_DMABurst and how to first start TIM_DMABurst

  • July 22, 2022
  • 5 replies
  • 2304 views

I try to use TIM_DMABurst to generate exact number of pwm pulses.

But I found after call HAL_TIM_DMABurst_WriteStart and HAL_TIM_PWM_Start, it enter HAL_TIM_PeriodElapsedCallback. And then if I call HAL_TIM_PWM_Stop it will stop and generate no pwm. If I call HAL_TIM_DMABurst_WriteStop and HAL_TIM_DMABurst_WriteStart it will continue generate PWM but the wave is wrong

    This topic has been closed for replies.

    5 replies

    dming.4
    dming.4Author
    Associate II
    July 22, 2022
    TIM_HandleTypeDef htim1;
    DMA_HandleTypeDef hdma_tim1_up;
     
    static uint32_t g_irq_cnt = 0;
    static uint32_t aSRC_Buffer[3];
     
    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();
     
     /* USER CODE BEGIN SysInit */
     
     /* USER CODE END SysInit */
     
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_DMA_Init();
     MX_TIM1_Init();
     /* USER CODE BEGIN 2 */
     aSRC_Buffer[0] = 7200 - 1; /* ARR */
     aSRC_Buffer[1] = 7 - 1; /* RCR */
     aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
     HAL_TIM_DMABurst_WriteStart(&htim1, TIM_DMABASE_ARR, TIM_DMA_UPDATE, aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
     HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
     // HAL_TIM_GenerateEvent(&htim1, TIM_EVENTSOURCE_UPDATE);
     /* USER CODE END 2 */
     
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     /* USER CODE END WHILE */
     HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
     HAL_Delay(500);
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */
    }
     
     
    /**
     * @brief Period elapsed callback in non blocking mode
     * @note This function is called when TIM7 interrupt took place, inside
     * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
     * a global variable "uwTick" used as application time base.
     * @param htim : TIM handle
     * @retval None
     */
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
     /* USER CODE BEGIN Callback 0 */
     if (htim->Instance == TIM1) {
    	 ++g_irq_cnt;
     
    	 if (g_irq_cnt == 1) {
    		 aSRC_Buffer[0] = 3600 - 1; /* ARR */
    		 aSRC_Buffer[1] = 7 - 1; /* RCR */
    		 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
    	 } else if (g_irq_cnt == 2) {
    		 aSRC_Buffer[0] = 1800 - 1; /* ARR */
    		 aSRC_Buffer[1] = 7 - 1; /* RCR */
    		 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.4; /* CCR1 */
    	 } else if (g_irq_cnt == 3) {
    	 		 aSRC_Buffer[0] = 900 - 1; /* ARR */
    	 		 aSRC_Buffer[1] = 7 - 1; /* RCR */
    	 		 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.6; /* CCR1 */
    	 	 }
     
    	 HAL_TIM_DMABurst_WriteStop(&htim1, TIM_DMA_UPDATE);
    	 // htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
    	 HAL_TIM_DMABurst_WriteStart(&htim1, TIM_DMABASE_ARR, TIM_DMA_UPDATE, aSRC_Buffer, TIM_DMABURSTLENGTH_3TRANSFERS);
     
    	if (g_irq_cnt >= 6) {
    		HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    	}
     }
     /* USER CODE END Callback 0 */
     if (htim->Instance == TIM7) {
     HAL_IncTick();
     }
     /* USER CODE BEGIN Callback 1 */
     
     /* USER CODE END Callback 1 */
    }
     
    static void MX_TIM1_Init(void)
    {
     
     /* USER CODE BEGIN TIM1_Init 0 */
     
     /* USER CODE END TIM1_Init 0 */
     
     TIM_ClockConfigTypeDef sClockSourceConfig = {0};
     TIM_MasterConfigTypeDef sMasterConfig = {0};
     TIM_OC_InitTypeDef sConfigOC = {0};
     TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
     
     /* USER CODE BEGIN TIM1_Init 1 */
     
     /* USER CODE END TIM1_Init 1 */
     htim1.Instance = TIM1;
     htim1.Init.Prescaler = 100 - 1;
     htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
     htim1.Init.Period = 65535;
     htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
     htim1.Init.RepetitionCounter = 0;
     htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
     if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
     {
     Error_Handler();
     }
     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
     if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
     {
     Error_Handler();
     }
     if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
     {
     Error_Handler();
     }
     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
     if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
     {
     Error_Handler();
     }
     sConfigOC.OCMode = TIM_OCMODE_PWM1;
     sConfigOC.Pulse = 0;
     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
     sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
     sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
     sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
     if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
     {
     Error_Handler();
     }
     sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
     sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
     sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
     sBreakDeadTimeConfig.DeadTime = 0;
     sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
     sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
     sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
     if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN TIM1_Init 2 */
     
     /* USER CODE END TIM1_Init 2 */
     HAL_TIM_MspPostInit(&htim1);
     
    }
     
    static void MX_DMA_Init(void)
    {
     
     /* DMA controller clock enable */
     __HAL_RCC_DMA1_CLK_ENABLE();
     
     /* DMA interrupt init */
     /* DMA1_Channel5_IRQn interrupt configuration */
     HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
     
    }
     
     
    /**
    * @brief TIM_Base MSP Initialization
    * This function configures the hardware resources used in this example
    * @param htim_base: TIM_Base handle pointer
    * @retval None
    */
    void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
    {
     if(htim_base->Instance==TIM1)
     {
     /* USER CODE BEGIN TIM1_MspInit 0 */
     
     /* USER CODE END TIM1_MspInit 0 */
     /* Peripheral clock enable */
     __HAL_RCC_TIM1_CLK_ENABLE();
     
     /* TIM1 DMA Init */
     /* TIM1_UP Init */
     hdma_tim1_up.Instance = DMA1_Channel5;
     hdma_tim1_up.Init.Direction = DMA_MEMORY_TO_PERIPH;
     hdma_tim1_up.Init.PeriphInc = DMA_PINC_DISABLE;
     hdma_tim1_up.Init.MemInc = DMA_MINC_ENABLE;
     hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
     hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
     hdma_tim1_up.Init.Mode = DMA_NORMAL;
     hdma_tim1_up.Init.Priority = DMA_PRIORITY_HIGH;
     if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)
     {
     Error_Handler();
     }
     
     __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);
     
     /* TIM1 interrupt Init */
     HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
     /* USER CODE BEGIN TIM1_MspInit 1 */
     
     /* USER CODE END TIM1_MspInit 1 */
     }
     
    }
     
    void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
    {
     GPIO_InitTypeDef GPIO_InitStruct = {0};
     if(htim->Instance==TIM1)
     {
     /* USER CODE BEGIN TIM1_MspPostInit 0 */
     
     /* USER CODE END TIM1_MspPostInit 0 */
     
     __HAL_RCC_GPIOA_CLK_ENABLE();
     /**TIM1 GPIO Configuration
     PA8 ------> TIM1_CH1
     */
     GPIO_InitStruct.Pin = GPIO_PIN_8;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
     
     /* USER CODE BEGIN TIM1_MspPostInit 1 */
     
     /* USER CODE END TIM1_MspPostInit 1 */
     }
     
    }

    dming.4
    dming.4Author
    Associate II
    July 22, 2022

    The core like this

    First start TIM_DMABrust with

     aSRC_Buffer[0] = 7200 - 1; /* ARR */
     aSRC_Buffer[1] = 7 - 1; /* RCR */
     aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */

    and then in the HAL_TIM_PeriodElapsedCallback change aSRC_Buffer

    	 if (g_irq_cnt == 1) {
    		 aSRC_Buffer[0] = 3600 - 1; /* ARR */
    		 aSRC_Buffer[1] = 7 - 1; /* RCR */
    		 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.2; /* CCR1 */
    	 } else if (g_irq_cnt == 2) {
    		 aSRC_Buffer[0] = 1800 - 1; /* ARR */
    		 aSRC_Buffer[1] = 7 - 1; /* RCR */
    		 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.4; /* CCR1 */
    	 } else if (g_irq_cnt == 3) {
    	 aSRC_Buffer[0] = 900 - 1; /* ARR */
     aSRC_Buffer[1] = 7 - 1; /* RCR */
    	 aSRC_Buffer[2] = (aSRC_Buffer[0] + 1) * 0.6; /* CCR1 */
     }

    but i get pluss like that

    0693W00000QLrR1QAL.png0693W00000QLrS4QAL.png0693W00000QLrSYQA1.png0693W00000QLrSxQAL.png0693W00000QLrT7QAL.pngand in the end it will generate a very small pluse

    0693W00000QLrTbQAL.png

    waclawek.jan
    Super User
    July 22, 2022

    Which STM32?

    > and then in the HAL_TIM_PeriodElapsedCallback change aSRC_Buffer

    But why?

    The point of DMA is, that it works without your intervention. So just define a long enough buffer to hold all the changes, and run the DMA and you're done. A nice trick to stop is to add one more set at the end, where ARR=0.

    JW

    dming.4
    dming.4Author
    Associate II
    July 22, 2022

    stm32f103

    I use this timer to driver a step motor ​ so it must be stop at the target point. Amd the problem is the wave generate by mcu is wrong. Use dmamultiwrite do not fix.