본문 바로가기
카테고리 없음

[STM32G474] PWM으로 전력변환 DC-DC 토폴로지별 PWM 생성 방법: HAL API 활용(2)

by linuxgo 2025. 8. 19.
반응형

1. STM32G474 PWM 및 DC-DC 컨버터 개요

STM32G474는 STMicroelectronics의 STM32G4 시리즈에 속하는 고성능 32비트 ARM Cortex-M4 마이크로컨트롤러로, 최대 170MHz로 동작하며 Advanced-Control 타이머(TIM1, TIM8)를 포함한 다양한 타이머 기능을 제공합니다. PWM(Pulse Width Modulation)은 DC-DC 컨버터(예: LLC Half-Bridge, LLC Full-Bridge, Phase-Shifted Full-Bridge)와 같은 전력변환 애플리케이션에서 스위칭 소자를 제어하는 데 필수적입니다. 이 문서에서는 STM32G474의 Advanced-Control 타이머를 HAL API로 사용하여 주요 DC-DC 컨버터 토폴로지(LLC Half-Bridge, LLC Full-Bridge, Phase-Shifted Full-Bridge)에 적합한 PWM 신호를 생성하는 방법을 상세히 다룹니다. 모든 예제 코드는 STM32CubeMX로 생성된 완전한 코드로 구성되며, STM32CubeIDE에서 실행 가능합니다. 각 코드에는 상세한 주석이 포함되어 있습니다.

PWM 모듈의 주요 특징

  • 타이머: Advanced-Control 타이머(TIM1, TIM8)는 PWM 출력, 보완 출력, 데드타임 삽입, 브레이크 입력을 지원.
  • 채널: 최대 4개의 PWM 채널(CH1CH4) 및 보완 출력(CH1NCH4N).
  • 모드: PWM Mode 1(에지 정렬), PWM Mode 2(중앙 정렬).
  • 분해능: 높은 PWM 분해능 제공(타이머 카운터 및 비교 레지스터).
  • 클럭: AHB/APB 클럭으로 동작, 저전력 모드 지원.
  • 고급 기능: 데드타임 삽입, 브레이크 입력, 반복 카운터.
  • DC-DC 컨버터 관련: 고주파 PWM(50 kHz~500 kHz), 보완 출력 및 데드타임은 LLC 및 PSFB에 적합.

HAL API는 복잡한 레지스터 설정을 추상화하여 PWM 설정을 간소화합니다.

2. 주요 PWM HAL API 함수

2.1. 타이머 및 PWM 초기화 함수

  •   *HAL_TIM_PWM_Init(TIM_HandleTypeDef htim)
    •   설명: 타이머를 PWM 모드로 초기화.
    •   매개변수: htim (타이머 핸들러 구조체).
  •   **HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef htim, TIM_OC_InitTypeDef sConfig, uint32_t Channel)
    •   설명: 특정 타이머 채널의 PWM 설정(듀티 사이클, 출력 극성 등).
  •   *HAL_TIM_PWM_Start(TIM_HandleTypeDef htim, uint32_t Channel)
    •   설명: PWM 출력 시작.
  •   *HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef htim, uint32_t Channel)
    •   설명: 보완 PWM 출력 시작.
  •   **HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef htim, TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig)
    •   설명: 데드타임 및 브레이크 입력 설정.

2.2. PWM 제어 함수

  •   *HAL_TIM_PWM_Pulse_Set(TIM_HandleTypeDef htim, uint32_t Channel, uint32_t Pulse)
    •   설명: PWM 듀티 사이클 설정.
  •   *HAL_TIM_PWM_Pulse_Get(TIM_HandleTypeDef htim, uint32_t Channel)
    •   설명: 현재 PWM 듀티 사이클 값 반환.

2.3. 인터럽트 관련 함수

  •   *HAL_TIM_PWM_IRQHandler(TIM_HandleTypeDef htim)
    •   설명: 타이머 PWM 인터럽트 핸들러.
  •   *HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef htim)
    •   설명: PWM 펄스 완료 시 호출되는 사용자 정의 콜백 함수.

3. DC-DC 컨버터 토폴로지별 PWM 요구사항

DC-DC 컨버터는 입력 전압을 원하는 출력 전압으로 변환하며, PWM 신호는 스위칭 소자(MOSFET, IGBT 등)를 제어하여 전력 흐름을 조절합니다. 각 토폴로지별 PWM 요구사항은 다음과 같습니다:

3.1. LLC Half-Bridge 컨버터

  •   특징: 공진형 컨버터로 고효율, 고주파 동작(100 kHz~500 kHz). 두 개의 스위치로 Half-Bridge 구성.
  •   PWM 요구사항:
    •   두 채널 PWM 신호(예: TIM1_CH1, TIM1_CH1N)로 상보적 출력, 50% 고정 듀티 사이클.
    •   주파수: 100 kHz~500 kHz (공진 주파수에 따라 조정).
    •   PWM Mode 2(중앙 정렬) 권장 (대칭적 스위칭).
    •   데드타임 필수 (스위치 단락 방지).
  •   예제 설정: 100 kHz PWM, 50% 듀티 사이클, 100 ns 데드타임.

3.2. LLC Full-Bridge 컨버터

  •   특징: 네 개의 스위치로 Full-Bridge 구성, 더 높은 전력 처리 가능.
  •   PWM 요구사항:
    •   네 개의 PWM 신호(예: TIM1_CH1, CH1N, CH2, CH2N)로 두 쌍의 상보적 출력.
    •   주파수: 100 kHz~500 kHz.
    •   PWM Mode 2 권장.
    •   데드타임 필수.
  •   예제 설정: 100 kHz PWM, 50% 듀티 사이클, 100 ns 데드타임.

3.3. Phase-Shifted Full-Bridge (PSFB) 컨버터

  •   특징: 위상 천이(Phase-Shift)로 ZVS(Zero Voltage Switching)를 구현, 고효율.
  •   PWM 요구사항:
    •   네 개의 PWM 신호(예: TIM1_CH1, CH1N, CH2, CH2N).
    •   위상 천이 제어: 두 채널 간 위상 차 조절.
    •   주파수: 50 kHz~200 kHz.
    •   PWM Mode 2 권장.
    •   데드타임 필수.
  •   예제 설정: 100 kHz PWM, 50% 듀티 사이클, 100 ns 데드타임, 위상 천이 조절.

4. PWM 설정 및 동작 원리

STM32G474의 PWM을 DC-DC 컨버터에 사용하려면 시스템 클럭, 타이머 설정, GPIO 설정, 디버깅 및 프로그램 다운로드 절차를 정확히 구성해야 합니다. 아래는 STM32CubeMX와 STM32CubeIDE를 사용한 설정 절차입니다.

4.1. STM32CubeMX 설정 절차

  1. 프로젝트 생성:
    •   STM32CubeMX에서 "New Project" 선택, "STM32G474" 검색, 패키지(예: LQFP64) 선택.
    •   프로젝트 이름 및 저장 경로 설정.
  2. 시스템 클럭 설정 (170 MHz, HSE 사용):
    •   "System Core" > "RCC"에서 HSE를 "Crystal/Ceramic Resonator"로 설정 (8 MHz 크리스털 가정).
    •   Clock Configuration:
      •   HSE: 8 MHz.
      •   PLL 설정: PLLM = 1, PLLN = 85, PLLR = 2, PLLR Enable.
      •   System Clock Mux: PLLCLK.
      •   결과: SYSCLK = (8 MHz / 1) * 85 / 2 = 170 MHz.
      •   HCLK, PCLK1, PCLK2: 170 MHz (Divider = 1).
      •   Flash Latency: 4 WS.
  3. PWM 설정:
    •   "Timers" > "TIM1" 선택.
    •   LLC Half-Bridge: Channel 1 (PA8, TIM1_CH1), Complementary Channel 1N (PA7, TIM1_CH1N).
    •   LLC Full-Bridge/PSFB: Channel 1 (PA8, TIM1_CH1), Channel 1N (PA7), Channel 2 (PA9, TIM1_CH2), Channel 2N (PB0, TIM1_CH2N).
    •   Parameter Settings:
      •   Prescaler (PSC): 16 (타이머 클럭 = 170 MHz / (16+1) = 10 MHz).
      •   Counter Period (ARR): 99 (PWM 주기 = (99+1) / 10 MHz = 10 µs, 주파수 = 100 kHz).
      •   Pulse: 50 (듀티 사이클 = 50%, 50/100).
      •   Mode: PWM Mode 2 (중앙 정렬).
      •   Dead Time: 100 ns.
    •   GPIO: PA8, PA7, PA9, PB0 자동 설정, 속도 "High".
  4. 디버깅 인터페이스 설정:
    •   "System Core" > "SYS"에서 Debug를 "Serial Wire" (SWD)로 설정.
    •   SWD 핀: PA13 (SWDIO), PA14 (SWCLK).
  5. 프로젝트 설정 및 코드 생성:
    •   Project Manager:
      •   Toolchain/IDE: STM32CubeIDE.
      •   Code Generator: "Copy only the necessary library files".
    •   "Generate Code" 클릭.

4.2. PWM 동작 원리

  1. 시스템 초기화:
    •   시스템 클럭 170 MHz, GPIO 및 타이머 클럭 활성화.
    •   HAL_Init()으로 HAL 라이브러리 및 Systick 초기화.
  2. PWM 설정:
    •   TIM1 설정 (TIM_OC_InitTypeDef 구조체).
    •   Prescaler와 ARR로 주파수 설정 (예: 100 kHz).
    •   Compare Register(CCR)로 듀티 사이클 설정.
    •   보완 출력 및 데드타임 설정 (LLC, PSFB).
    •   PSFB의 경우 위상 천이 구현.
  3. PWM 동작:
    •   HAL_TIM_PWM_Start 및 HAL_TIMEx_PWMN_Start로 PWM 출력 시작.
    •   HAL_TIM_PWM_Pulse_Set으로 듀티 사이클 동적 조절.
    •   인터럽트로 위상 천이 및 동적 제어 가능.

4.3. 디버깅 및 프로그램 다운로드

  • 디버깅:
    •   ST-LINK 연결 (SWDIO: PA13, SWCLK: PA14).
    •   STM32CubeIDE에서 "Debug Configurations" 설정 (ST-LINK, SWD).
    •   브레이크포인트 및 변수 모니터링 (pwmPulse 등).
  • 프로그램 다운로드:
    •   "Build Project"로 빌드.
    •   "Run Configurations"에서 .elf 파일 선택 후 다운로드.
    •   오실로스코프로 PWM 파형 및 데드타임 확인.

5. PWM 예제 코드

아래는 STM32G474의 TIM1을 HAL API로 사용하여 DC-DC 컨버터 토폴로지별 PWM 신호를 생성하는 예제 코드입니다. 코드는 STM32CubeIDE에서 실행 가능하며, HSE 8 MHz로 170 MHz SYSCLK를 설정합니다.

5.1. 예제 1: LLC Half-Bridge 컨버터 PWM (Mode 2)

TIM1 채널 1(PA8) 및 보완 출력(PA7)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 50% 고정 듀티 사이클, 100 ns 데드타임.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * STM32CubeMX-generated code for TIM1 Channel 1 (PA8) and Complementary Channel 1N (PA7) PWM output in Mode 2 for LLC Half-Bridge converter.
  * PWM frequency: 100 kHz, fixed 50% duty cycle, dead time: 100 ns.
  * System clock set to 170 MHz using HSE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
TIM_HandleTypeDef htim1; // TIM1 핸들러 구조체
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PWM_Pin GPIO_PIN_8 // PA8 핀을 PWM 출력으로 사용 (TIM1_CH1)
#define PWM_N_Pin GPIO_PIN_7 // PA7 핀을 보완 PWM 출력으로 사용 (TIM1_CH1N)
#define PWM_GPIO_Port GPIOA // PWM이 연결된 GPIO 포트
/* USER CODE END PD */

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

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t pwmStatus = 0; // PWM 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint32_t pwmPulse = 50; // PWM 펄스 값 (듀티 사이클 50%, 50/100)
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_TIM1_Init(void); // TIM1 초기화 함수 선언

/* 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(); // HAL 라이브러리 및 시스템 타이머(Systick) 초기화

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init(); // GPIOA 핀 8 및 7를 PWM 출력으로 초기화
  MX_TIM1_Init(); // TIM1를 PWM Mode 2로 초기화
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1 PWM 출력 시작
  HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1N 보완 출력 시작
  if (pwmStatus != 1) // PWM 초기화 성공 여부 확인
  {
    pwmStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
    while (1); // 오류 발생 시 무한 루프
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    // LLC Half-Bridge는 50% 고정 듀티 사이클 사용, 주파수 조절은 공진 탱크 설계에 따라 별도 구현
    /* USER CODE END WHILE */

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

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
  RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
  RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
  RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) // 오실레이터 설정 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; // 설정할 클럭 종류 지정
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화

  /*Configure GPIO pins : PA8, PA7 */
  GPIO_InitStruct.Pin = PWM_Pin | PWM_N_Pin; // 설정할 핀: GPIOA 핀 8 (CH1), 핀 7 (CH1N)
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 대체 기능, 푸시-풀
  GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 출력 속도: 고속
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; // PA8, PA7을 TIM1_CH1, TIM1_CH1N으로 설정
  HAL_GPIO_Init(PWM_GPIO_Port, &GPIO_InitStruct); // GPIOA 핀 설정 적용

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{
  TIM_OC_InitTypeDef sConfigOC = {0}; // 타이머 출력 비교 구조체 초기화
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; // 브레이크 및 데드타임 구조체 초기화

  htim1.Instance = TIM1; // TIM1 선택
  htim1.Init.Prescaler = 16; // 프리스케일러: 170 MHz / (16+1) = 10 MHz
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; // 중앙 정렬 모드 1 (PWM Mode 2)
  htim1.Init.Period = 99; // ARR: (99+1) / 10 MHz = 10 µs (100 kHz PWM)
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 클럭 분주 없음
  htim1.Init.RepetitionCounter = 0; // 반복 카운터 비활성화
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) // TIM1 PWM 모드 초기화
  {
    Error_Handler(); // 초기화 실패 시 오류 처리
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM2; // PWM 모드 2 (중앙 정렬)
  sConfigOC.Pulse = 50; // 펄스 값: 50% 듀티 사이클 (50/100)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 출력 극성: High
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; // 보완 출력 극성: High
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 빠른 모드 비활성화
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) // 채널 1 PWM 설정
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; // 런 모드 오프 상태 비활성화
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; // 유휴 상태 비활성화
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; // 락 레벨 비활성화
  sBreakDeadTimeConfig.DeadTime = 100; // 데드타임: 100 ns (10 MHz 클럭 기준)
  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(); // 설정 실패 시 오류 처리
  }

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/* USER CODE BEGIN 4 */

/* 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 */
  pwmStatus = 0xFFFF; // 오류 상태 설정
  while (1) // 무한 루프에서 대기
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  while (1) // 어설션 오류 시 무한 루프
  {
  }
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

설명:

  • 기능: TIM1 채널 1(PA8) 및 보완 출력(PA7)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 50% 고정 듀티 사이클, 100 ns 데드타임으로 LLC Half-Bridge 스위치 제어.
  • 설정: PWM 주파수 100 kHz (PSC=16, ARR=99), 듀티 사이클 50% (Pulse=50), PWM Mode 2, 데드타임 100 ns.
  • GPIO: GPIOA 핀 8 (TIM1_CH1), GPIOA 핀 7 (TIM1_CH1N).
  • 출력: PWM 파형은 PA8과 PA7에서 상보적으로 출력, 고정 50% 듀티 사이클.
  • 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.

5.2. 예제 2: LLC Full-Bridge 컨버터 PWM (Mode 2)

TIM1 채널 1(PA8), 채널 1N(PA7), 채널 2(PA9), 채널 2N(PB0)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 50% 고정 듀티 사이클, 100 ns 데드타임.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * STM32CubeMX-generated code for TIM1 Channels 1, 1N, 2, 2N (PA8, PA7, PA9, PB0) PWM output in Mode 2 for LLC Full-Bridge converter.
  * PWM frequency: 100 kHz, fixed 50% duty cycle, dead time: 100 ns.
  * System clock set to 170 MHz using HSE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
TIM_HandleTypeDef htim1; // TIM1 핸들러 구조체
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PWM_CH1_Pin GPIO_PIN_8 // PA8 핀을 PWM 출력으로 사용 (TIM1_CH1)
#define PWM_CH1N_Pin GPIO_PIN_7 // PA7 핀을 보완 PWM 출력으로 사용 (TIM1_CH1N)
#define PWM_CH2_Pin GPIO_PIN_9 // PA9 핀을 PWM 출력으로 사용 (TIM1_CH2)
#define PWM_CH2N_Pin GPIO_PIN_0 // PB0 핀을 보완 PWM 출력으로 사용 (TIM1_CH2N)
#define PWM_GPIO_Port_A GPIOA // PWM CH1, CH1N, CH2가 연결된 GPIO 포트
#define PWM_GPIO_Port_B GPIOB // PWM CH2N이 연결된 GPIO 포트
/* USER CODE END PD */

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

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t pwmStatus = 0; // PWM 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint32_t pwmPulse = 50; // PWM 펄스 값 (듀티 사이클 50%, 50/100)
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_TIM1_Init(void); // TIM1 초기화 함수 선언

/* 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(); // HAL 라이브러리 및 시스템 타이머(Systick) 초기화

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init(); // GPIOA 핀 8, 7, 9 및 GPIOB 핀 0를 PWM 출력으로 초기화
  MX_TIM1_Init(); // TIM1를 PWM Mode 2로 초기화
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1 PWM 출력 시작
  HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1N 보완 출력 시작
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // TIM1 채널 2 PWM 출력 시작
  HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2); // TIM1 채널 2N 보완 출력 시작
  if (pwmStatus != 1) // PWM 초기화 성공 여부 확인
  {
    pwmStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
    while (1); // 오류 발생 시 무한 루프
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    // LLC Full-Bridge는 50% 고정 듀티 사이클 사용, 주파수 조절은 공진 탱크 설계에 따라 별도 구현
    /* USER CODE END WHILE */

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

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
  RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
  RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
  RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) // 오실레이터 설정 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; // 설정할 클럭 종류 지정
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화
  __HAL_RCC_GPIOB_CLK_ENABLE(); // GPIOB 포트 클럭 활성화

  /*Configure GPIO pins : PA8, PA7, PA9 */
  GPIO_InitStruct.Pin = PWM_CH1_Pin | PWM_CH1N_Pin | PWM_CH2_Pin; // 설정할 핀: GPIOA 핀 8, 7, 9
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 대체 기능, 푸시-풀
  GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 출력 속도: 고속
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; // PA8, PA7, PA9를 TIM1_CH1, CH1N, CH2로 설정
  HAL_GPIO_Init(PWM_GPIO_Port_A, &GPIO_InitStruct); // GPIOA 핀 설정 적용

  /*Configure GPIO pin : PB0 */
  GPIO_InitStruct.Pin = PWM_CH2N_Pin; // 설정할 핀: GPIOB 핀 0 (CH2N)
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 대체 기능, 푸시-풀
  GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 출력 속도: 고속
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; // PB0를 TIM1_CH2N으로 설정
  HAL_GPIO_Init(PWM_GPIO_Port_B, &GPIO_InitStruct); // GPIOB 핀 설정 적용

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{
  TIM_OC_InitTypeDef sConfigOC = {0}; // 타이머 출력 비교 구조체 초기화
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; // 브레이크 및 데드타임 구조체 초기화

  htim1.Instance = TIM1; // TIM1 선택
  htim1.Init.Prescaler = 16; // 프리스케일러: 170 MHz / (16+1) = 10 MHz
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; // 중앙 정렬 모드 1 (PWM Mode 2)
  htim1.Init.Period = 99; // ARR: (99+1) / 10 MHz = 10 µs (100 kHz PWM)
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 클럭 분주 없음
  htim1.Init.RepetitionCounter = 0; // 반복 카운터 비활성화
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) // TIM1 PWM 모드 초기화
  {
    Error_Handler(); // 초기화 실패 시 오류 처리
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM2; // PWM 모드 2 (중앙 정렬)
  sConfigOC.Pulse = 50; // 펄스 값: 50% 듀티 사이클 (50/100)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 출력 극성: High
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; // 보완 출력 극성: High
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 빠른 모드 비활성화
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) // 채널 1 PWM 설정
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) // 채널 2 PWM 설정
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; // 런 모드 오프 상태 비활성화
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; // 유휴 상태 비활성화
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; // 락 레벨 비활성화
  sBreakDeadTimeConfig.DeadTime = 100; // 데드타임: 100 ns (10 MHz 클럭 기준)
  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(); // 설정 실패 시 오류 처리
  }

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/* USER CODE BEGIN 4 */

/* 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 */
  pwmStatus = 0xFFFF; // 오류 상태 설정
  while (1) // 무한 루프에서 대기
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  while (1) // 어설션 오류 시 무한 루프
  {
  }
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

설명:

  • 기능: TIM1 채널 1(PA8), 채널 1N(PA7), 채널 2(PA9), 채널 2N(PB0)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 50% 고정 듀티 사이클, 100 ns 데드타임으로 LLC Full-Bridge 스위치 제어.
  • 설정: PWM 주파수 100 kHz (PSC=16, ARR=99), 듀티 사이클 50% (Pulse=50), PWM Mode 2, 데드타임 100 ns.
  • GPIO: GPIOA 핀 8, 7, 9 (TIM1_CH1, CH1N, CH2), GPIOB 핀 0 (TIM1_CH2N).
  • 출력: PWM 파형은 PA8, PA7, PA9, PB0에서 상보적으로 출력, 고정 50% 듀티 사이클.
  • 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.

5.3. 예제 3: Phase-Shifted Full-Bridge (PSFB) 컨버터 PWM (Mode 2)

TIM1 채널 1(PA8), 채널 1N(PA7), 채널 2(PA9), 채널 2N(PB0)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 위상 천이 조절, 100 ns 데드타임.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * STM32CubeMX-generated code for TIM1 Channels 1, 1N, 2, 2N (PA8, PA7, PA9, PB0) PWM output in Mode 2 for Phase-Shifted Full-Bridge converter.
  * PWM frequency: 100 kHz, 50% duty cycle, dead time: 100 ns, phase shift adjustable.
  * System clock set to 170 MHz using HSE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
TIM_HandleTypeDef htim1; // TIM1 핸들러 구조체
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define PWM_CH1_Pin GPIO_PIN_8 // PA8 핀을 PWM 출력으로 사용 (TIM1_CH1)
#define PWM_CH1N_Pin GPIO_PIN_7 // PA7 핀을 보완 PWM 출력으로 사용 (TIM1_CH1N)
#define PWM_CH2_Pin GPIO_PIN_9 // PA9 핀을 PWM 출력으로 사용 (TIM1_CH2)
#define PWM_CH2N_Pin GPIO_PIN_0 // PB0 핀을 보완 PWM 출력으로 사용 (TIM1_CH2N)
#define PWM_GPIO_Port_A GPIOA // PWM CH1, CH1N, CH2가 연결된 GPIO 포트
#define PWM_GPIO_Port_B GPIOB // PWM CH2N이 연결된 GPIO 포트
/* USER CODE END PD */

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

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint32_t pwmStatus = 0; // PWM 상태 변수: 0 (초기화 완료), 1 (동작 중), 0xFFFF (오류)
volatile uint32_t pwmPulse = 50; // PWM 펄스 값 (듀티 사이클 50%, 50/100)
volatile uint32_t phaseShift = 0; // 위상 천이 값 (0~99, 단위: 타이머 카운트)
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void); // 시스템 클럭 설정 함수 선언
static void MX_GPIO_Init(void); // GPIO 초기화 함수 선언
static void MX_TIM1_Init(void); // TIM1 초기화 함수 선언

/* 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(); // HAL 라이브러리 및 시스템 타이머(Systick) 초기화

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config(); // 시스템 클럭을 170 MHz로 설정 (HSE 8 MHz 사용)

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init(); // GPIOA 핀 8, 7, 9 및 GPIOB 핀 0를 PWM 출력으로 초기화
  MX_TIM1_Init(); // TIM1를 PWM Mode 2로 초기화
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1 PWM 출력 시작
  HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // TIM1 채널 1N 보완 출력 시작
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // TIM1 채널 2 PWM 출력 시작
  HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2); // TIM1 채널 2N 보완 출력 시작
  if (pwmStatus != 1) // PWM 초기화 성공 여부 확인
  {
    pwmStatus = 0xFFFF; // 초기화 실패 시 오류 상태 설정
    while (1); // 오류 발생 시 무한 루프
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    // 위상 천이를 0~99까지 점진적으로 변경 (PSFB 출력 전력 조절)
    for (phaseShift = 0; phaseShift <= 99; phaseShift += 1)
    {
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, pwmPulse + phaseShift); // 채널 2에 위상 천이 적용
      HAL_Delay(50); // 50ms 대기
    }
    for (phaseShift = 99; phaseShift >= 0; phaseShift -= 1)
    {
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, pwmPulse + phaseShift); // 채널 2에 위상 천이 적용
      HAL_Delay(50); // 50ms 대기
    }
    /* USER CODE END WHILE */

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

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // 오실레이터 설정 구조체 초기화
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // 클럭 설정 구조체 초기화

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // 전압 레귤레이터를 Scale 1로 설정 (최대 성능)

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 외부 HSE 오실레이터 사용
  RCC_OscInitStruct.HSEState = RCC_HSE_ON; // HSE 활성화
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // PLL 활성화
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL 소스를 HSE로 설정
  RCC_OscInitStruct.PLL.PLLM = 1; // PLL 분주기 M = 1
  RCC_OscInitStruct.PLL.PLLN = 85; // PLL 곱셈기 N = 85
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLL P 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; // PLL Q 출력 분주기 = 2
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; // PLL R 출력 분주기 = 2 (SYSCLK = 8 MHz * 85 / 2 = 170 MHz)
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) // 오실레이터 설정 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; // 설정할 클럭 종류 지정
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 시스템 클럭 소스를 PLL로 설정
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB 클럭 분주기 = 1 (HCLK = 170 MHz)
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // APB1 클럭 분주기 = 1 (PCLK1 = 170 MHz)
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2 클럭 분주기 = 1 (PCLK2 = 170 MHz)

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) // 클럭 설정 및 플래시 레이턴시 4 WS 적용
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO 설정 구조체 초기화

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE(); // GPIOA 포트 클럭 활성화
  __HAL_RCC_GPIOB_CLK_ENABLE(); // GPIOB 포트 클럭 활성화

  /*Configure GPIO pins : PA8, PA7, PA9 */
  GPIO_InitStruct.Pin = PWM_CH1_Pin | PWM_CH1N_Pin | PWM_CH2_Pin; // 설정할 핀: GPIOA 핀 8, 7, 9
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 대체 기능, 푸시-풀
  GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 출력 속도: 고속
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; // PA8, PA7, PA9를 TIM1_CH1, CH1N, CH2로 설정
  HAL_GPIO_Init(PWM_GPIO_Port_A, &GPIO_InitStruct); // GPIOA 핀 설정 적용

  /*Configure GPIO pin : PB0 */
  GPIO_InitStruct.Pin = PWM_CH2N_Pin; // 설정할 핀: GPIOB 핀 0 (CH2N)
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 대체 기능, 푸시-풀
  GPIO_InitStruct.Pull = GPIO_NOPULL; // 풀업/풀다운 저항 사용 안 함
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 출력 속도: 고속
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; // PB0를 TIM1_CH2N으로 설정
  HAL_GPIO_Init(PWM_GPIO_Port_B, &GPIO_InitStruct); // GPIOB 핀 설정 적용

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{
  TIM_OC_InitTypeDef sConfigOC = {0}; // 타이머 출력 비교 구조체 초기화
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; // 브레이크 및 데드타임 구조체 초기화

  htim1.Instance = TIM1; // TIM1 선택
  htim1.Init.Prescaler = 16; // 프리스케일러: 170 MHz / (16+1) = 10 MHz
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; // 중앙 정렬 모드 1 (PWM Mode 2)
  htim1.Init.Period = 99; // ARR: (99+1) / 10 MHz = 10 µs (100 kHz PWM)
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 클럭 분주 없음
  htim1.Init.RepetitionCounter = 0; // 반복 카운터 비활성화
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) // TIM1 PWM 모드 초기화
  {
    Error_Handler(); // 초기화 실패 시 오류 처리
  }

  sConfigOC.OCMode = TIM_OCMODE_PWM2; // PWM 모드 2 (중앙 정렬)
  sConfigOC.Pulse = 50; // 펄스 값: 50% 듀티 사이클 (50/100)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 출력 극성: High
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; // 보완 출력 극성: High
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 빠른 모드 비활성화
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) // 채널 1 PWM 설정
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) // 채널 2 PWM 설정
  {
    Error_Handler(); // 설정 실패 시 오류 처리
  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; // 런 모드 오프 상태 비활성화
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; // 유휴 상태 비활성화
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; // 락 레벨 비활성화
  sBreakDeadTimeConfig.DeadTime = 100; // 데드타임: 100 ns (10 MHz 클럭 기준)
  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(); // 설정 실패 시 오류 처리
  }

  pwmStatus = 1; // PWM 초기화 성공 표시
}

/* USER CODE BEGIN 4 */

/* 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 */
  pwmStatus = 0xFFFF; // 오류 상태 설정
  while (1) // 무한 루프에서 대기
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  while (1) // 어설션 오류 시 무한 루프
  {
  }
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

설명:

  • 기능: TIM1 채널 1(PA8), 채널 1N(PA7), 채널 2(PA9), 채널 2N(PB0)에서 100 kHz PWM 신호를 PWM Mode 2로 출력, 50% 듀티 사이클, 100 ns 데드타임, 위상 천이(0~99)로 PSFB 스위치 제어.
  • 설정: PWM 주파수 100 kHz (PSC=16, ARR=99), 듀티 사이클 50% (Pulse=50), PWM Mode 2, 데드타임 100 ns, 위상 천이 동적 조절.
  • GPIO: GPIOA 핀 8, 7, 9 (TIM1_CH1, CH1N, CH2), GPIOB 핀 0 (TIM1_CH2N).
  • 출력: PWM 파형은 PA8, PA7, PA9, PB0에서 상보적으로 출력, 채널 2에 위상 천이 적용.
  • 클럭: HSE 8 MHz, PLL로 170 MHz SYSCLK.

6. 추가 고려 사항

  • 주파수 선택: LLC 컨버터는 공진 주파수에 맞춰 100 kHz500 kHz, PSFB는 50 kHz200 kHz 사용.
  • 데드타임: 스위치 단락 방지를 위해 필수, 100 ns는 일반적인 값.
  • 피드백 제어: 실제 애플리케이션에서는 ADC로 출력 전압/전류를 모니터링하여 주파수 또는 위상 천이 동적 조절.
  • 디버깅: 오실로스코프로 PWM 파형, 데드타임, 위상 천이 확인.
  • 저전력: GPIO 속도 및 타이머 설정 최적화로 전력 소모 감소.

키워드: STM32G474, PWM, HAL API, STM32G4, DC-DC 컨버터, LLC Half-Bridge, LLC Full-Bridge, Phase-Shifted Full-Bridge, Advanced-Control 타이머, PWM Mode 2, 보완 출력, 데드타임, 위상 천이, STM32CubeIDE, STM32CubeMX, HSE 클럭, 디버깅

반응형