Проблемы STM32G0 с прерыванием по таймеру PWM не работает правильно

Я хочу использовать stm32 для генерации ШИМ-сигнала, но я должен иметь возможность изменять рабочий цикл после каждого сигнала. Моя проблема в том, что если я попробую, это не сработает правильно. Он отправляет 3-5 импульсов с одинаковым рабочим циклом, а затем изменяет значение. Я не понимаю, почему он меняет его после каждого импульса. И есть еще одна проблема: мне нужно повторно включать бит CCER для канала после каждого импульса, иначе он будет сброшен по любой причине.

Я использую плату STM32G071 Nucleo-64 с Keil uVision 5

Я создал начало с помощью STM32CubeMX и добавил свой код, чтобы он работал, но это не так. Я не знаю, что делать по-другому. Буду рад совету.

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define HIGH_PWM_SIGNAL     70//( 45 )
#define LOW_PWM_SIGNAL      10//( 27 )

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;

/* USER CODE BEGIN PV */
uint8_t PWM_Count = 0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM3_Init(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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_TIM3_Init();

  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */

    HAL_TIM_Base_Start_IT( &htim3 );
    HAL_TIM_PWM_Start_IT( &htim3, TIM_CHANNEL_1 );

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {


    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  // STM32CUbeMX generated deleted for readablitity
}

/**
  * @brief NVIC Configuration.
  * @retval None
  */
static void MX_NVIC_Init(void)
{
  /* TIM3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(TIM3_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */
    HAL_TIM_Base_DeInit( &htim3 );
    HAL_TIM_PWM_DeInit( &htim3 );

  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 80;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 10;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */
    HAL_NVIC_SetPriority( TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ( TIM3_IRQn );
    // Update interrupt
    HAL_TIM_GenerateEvent( &htim3, TIM_EVENTSOURCE_UPDATE );
    // PWM interrupt
    HAL_TIM_GenerateEvent( &htim3, TIM_EVENTSOURCE_CC1 );

  /* USER CODE END TIM3_Init 2 */
  HAL_TIM_MspPostInit(&htim3);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  // STM32CUbeMX generated deleted for readablitity
}

/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim){

       // Change PWM Duty Cycle

    PWM_Count += 1;
    if ( PWM_Count > 1 ) 
        PWM_Count = 0;

    if ( PWM_Count == 0 ) TIM3->CCR1  = LOW_PWM_SIGNAL;
    else    TIM3->CCR1  = HIGH_PWM_SIGNAL;

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ 

   // I have to re enable it or it doesn't output anything

   TIM_CCxChannelCmd(htim3.Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);


}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

Он не меняет рабочий цикл для каждого сигнала, который ему нужен, около 3-5 сигналов, а затем он меняет рабочий цикл. Осциллограф: выходной канал ШИМ1


person Allinev    schedule 11.11.2019    source источник
comment
Он входит в ISR, когда вы ставите там точку останова?   -  person Lundin    schedule 11.11.2019
comment
Да. Он поочередно входит в прерывание PulsFinished и Period elapsed.   -  person Allinev    schedule 11.11.2019
comment
Я проверил системные часы, и он работает на 64 МГц, и я попытался сделать это с другим таймером, но он такой же. Я действительно не знаю, что еще я мог бы попробовать.   -  person Allinev    schedule 11.11.2019


Ответы (1)


Я нашел решение. Я использовал библиотеку «stm32g0xx_hal_tim.c», которая оказалась весьма удобной. Но на это ушло много времени.

Он создан для работы с каждой проблемой и поэтому проверяет все (все флаги прерываний). Это много «если еще», на которые нужно время.

Я сам запрограммировал, что он проверяет только то, что мне нужно, и тогда это сработало.

Спасибо за помощь.

person Allinev    schedule 12.11.2019