Skocz do zawartości

Pomocna odpowiedź

Napisano (edytowany)

Potrzebuję wygenerować sygnały PWM na czterech wyjściach mikrokontrolera, specyfika jest taka: przed podaniem pierwszego pulsu - nazwijmy go roboczo preimpuls muszę mieć nieco czasu na uruchomienie innych peryferii ADC i/lub komparatora, ten preimpuls powinien trwać około 20μS po czym należy odczekać 10...20μS na odpowiedź układów peryferyjnych. Po tej odpowiedzi należy podjąć decyzję czy generować impuls główny na kolejnym kanale PWM. Impuls główny powinien być regulowany w czasie trwania z zewnętrznego urządzenia. Następnie cykl powtarza się dla drugiej pary. Do tej pory próbowałem wykorzystać timer1 z DMA jednak ze względu na ograniczoną szybkość działania nie umiem uzyskać przerwy krótszej niż te 200μS co spowalnia ogólną częstotliwość powtórzeń, no i jak dla tak prostego rozwiązania zużywa niepotrzebnie cztery kanały DMA. Potrzebuję raczej koncepcji, naprowadzenia, niż gotowego rozwiązania, nie wiem może użyć licznika zdarzeń i trybu triggera? Chętnie wykluczyłbym też DMA w tym miejscu bo sygnały nie są aż tak skomplikowane.
roboczo mam funkcję która generuje te powtórzenia, wygląda tak (narazie dla dwóch kanałów)

 

/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */

# define  tab_size  3

  uint32_t pre_puls[tab_size] =    {800,0,0};
  uint32_t main_puls[tab_size] =   {0,4000,0};


 // HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,pre_puls,10 );
 // HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_2,main_puls,10 );
 // __HAL_TIM_MOE_ENABLE(&htim1);


  //HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  // HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
  // HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);


  uint16_t pwm1 = 0;
  int8_t dir = 1;
  int counter = 0;
  for(;;)
  {
    counter++;
    vTaskDelay(1/portTICK_RATE_MS);
    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
if (counter < 1000) {
  HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,pre_puls,tab_size *2 );
  HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_2,main_puls,tab_size*2);
}
  }
  /* USER CODE END StartTask02 */
}

init
 

/* TIM1 init function */
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 = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 9999;
  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.MasterOutputTrigger2 = TIM_TRGO2_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_ENABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != 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.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  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);

}

Powyższy program generuje takie sygnały, dość blisko tego czego poszukuję ale to wciąż za długo trwa
Logic_Js5cJDub7v.thumb.png.396226ef8c6f3a9dd9a01d6a7012f1d6.png

Edytowano przez _LM_
Dnia 6.07.2025 o 12:29, _LM_ napisał:

Impuls główny powinien być regulowany w czasie trwania z zewnętrznego urządzenia.

Co dokładnie masz na myśli tutaj?

Ogólnie już jestem do przodu o tyle że pozbyłem się DMA z obsługi timerów, rzeczywiście nie jest potrzebne do generowania prostych impulsów. Na teraz udało się mi to zrobić na tim1 jako generator pierwszego impulsu i wyzwalania tim2 w trybie podrzędnym. Będzie nieco czasu to znów do tego usiądę

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...