Генерирование ШИМ с помощью DMA (HAL)

Тема в разделе "STM8/STM32", создана пользователем gruffi, 24 авг 2019.

  1. gruffi

    gruffi Частый гость

    Сообщения:
    2
    Симпатии:
    1
    Добрый день, форумчане.
    Возникла проблема при генерировании ШИМ. Задаю массив из трех чисел и передавал их через DMA
    Код:
    uint16_t data[3] = { 100, 250, 400 };
    HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t*)data, 3);
    Но генерирование начинается со скважности, которая была указана изначально при настройке (там стоит скважность 250) и только потом уже идет генерирование с необходимой скважностью. Понятно, что данные в ARR и CCRx обновляются при событии UEV, но проблема в том, что генерирование события через
    Код:
    htim4.Instance->EGR |= TIM_EGR_UG;
    htim4.Instance->SR &= ~TIM_SR_UIF;
    не дает никакого эффекта. При пошаговой отладке (использую Stm32CubeIDE) заметил что регистр EGR не активен, т.е. ни стоит никаких значений...
    Сделал следующим образом:
    Код:
    uint16_t data[3] = { 100, 250, 400 };
    
        TIM_OC_InitTypeDef sConfigOC = {0};
        sConfigOC.OCMode = TIM_OCMODE_PWM1;
        sConfigOC.Pulse = data[0];
        sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
        sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
        if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
        {
            Error_Handler();
        }
    
        htim4.Instance->EGR |= TIM_EGR_UG;
        htim4.Instance->SR &= ~TIM_SR_UIF;
        HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t*)data, 3);
    Но в этом случает получается, что дважды генерируется сигнал с первым значение скважности, т.е. со значение 100.

    Вот то что нагенерировал Куб:
    Код:
    void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
    {
      if(htim_base->Instance==TIM4)
      {
      /* USER CODE BEGIN TIM4_MspInit 0 */
    
      /* USER CODE END TIM4_MspInit 0 */
        /* Peripheral clock enable */
        __HAL_RCC_TIM4_CLK_ENABLE();
    
        /* TIM4 DMA Init */
        /* TIM4_CH1 Init */
        hdma_tim4_ch1.Instance = DMA1_Channel1;
        hdma_tim4_ch1.Init.Request = DMA_REQUEST_6;
        hdma_tim4_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
        hdma_tim4_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_tim4_ch1.Init.MemInc = DMA_MINC_ENABLE;
        hdma_tim4_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
        hdma_tim4_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_tim4_ch1.Init.Mode = DMA_NORMAL;
        hdma_tim4_ch1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
        if (HAL_DMA_Init(&hdma_tim4_ch1) != HAL_OK)
        {
          Error_Handler();
        }
    
        __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_CC1],hdma_tim4_ch1);
    
      /* USER CODE BEGIN TIM4_MspInit 1 */
    
      /* USER CODE END TIM4_MspInit 1 */
      }
    
    }
    
    void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(htim->Instance==TIM4)
      {
      /* USER CODE BEGIN TIM4_MspPostInit 0 */
    
      /* USER CODE END TIM4_MspPostInit 0 */
    
        __HAL_RCC_GPIOB_CLK_ENABLE();
        /**TIM4 GPIO Configuration
        PB6     ------> TIM4_CH1
        */
        GPIO_InitStruct.Pin = GPIO_PIN_6;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
      /* USER CODE BEGIN TIM4_MspPostInit 1 */
    
      /* USER CODE END TIM4_MspPostInit 1 */
      }
    
    }
    /**
    * @brief TIM_Base MSP De-Initialization
    * This function freeze the hardware resources used in this example
    * @param htim_base: TIM_Base handle pointer
    * @retval None
    */
    void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
    {
      if(htim_base->Instance==TIM4)
      {
      /* USER CODE BEGIN TIM4_MspDeInit 0 */
    
      /* USER CODE END TIM4_MspDeInit 0 */
        /* Peripheral clock disable */
        __HAL_RCC_TIM4_CLK_DISABLE();
    
        /* TIM4 DMA DeInit */
        HAL_DMA_DeInit(htim_base->hdma[TIM_DMA_ID_CC1]);
      /* USER CODE BEGIN TIM4_MspDeInit 1 */
    
      /* USER CODE END TIM4_MspDeInit 1 */
      }
    
    }
    С HAL опыта мало, в основном использовал только CMSIS, но сейчас необходимо сделать через HAL. Пните, где я натупил. Спасибо.

    image.png image2.png
    Последнее редактирование: 24 авг 2019
     
    : STM32, hal, dma
  2. gruffi

    gruffi Частый гость

    Сообщения:
    2
    Симпатии:
    1
    Немного затупил :)
    После генерирования события UEV я снова передаю 3 величины скважности и получаю дублирование двух одинаковых интервалов.
    Код:
    uint16_t data[3] = { 100, 250, 400 };
    
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = data[0];
    sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    
    if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
            Error_Handler();
    }
    
    htim4.Instance->EGR |= TIM_EGR_UG;
    htim4.Instance->SR &= ~TIM_SR_UIF;
    
    HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t*)&data[1], sizeof(data) - 1);
    Так заработало нормально :)
    Buba_Chkhadze нравится это.

Поделиться этой страницей