STM32 마이크로컨트롤러를 사용해 PWM 신호(PWM signal)를 생성할 때 Soft Start(소프트 스타트, Soft Start) 기능을 구현하는 방법을 알아보겠습니다 . Soft Start는 PWM 듀티 사이클(PWM duty cycle)을 점진적으로 증가시켜 모터, LED, 전원 공급 장치 등의 부하에서 급격한 전류 변화를 방지합니다. 이 글에서는 STM32CubeMX와 HAL 라이브러리(HAL library)를 사용한 두 가지 구현 방법(소프트웨어 기반, 타이머 인터럽트 기반)을 상세한 주석이 포함된 예제 코드와 함께 설명합니다 . 초보자도 쉽게 따라 할 수 있도록 구성했습니다
키워드 (Keywords): STM32 PWM, Soft Start, 듀티 사이클 (Duty Cycle), 타이머 인터럽트 (Timer Interrupt), STM32CubeMX
Soft Start란
Soft Start는 PWM 신호의 듀티 사이클을 0%에서 목표값까지 천천히 증가시켜 부하에 가해지는 충격을 줄이는 기술입니다. 모터의 급격한 회전이나 LED의 갑작스러운 밝기 변화를 방지하여 시스템 안정성을 높입니다. STM32에서는 타이머(Timer)를 활용해 PWM을 생성하고, 소프트웨어 또는 인터럽트를 통해 소프트 스타트(Soft Start)를 구현합니다
구현 방법
STM32에서 PWM Soft Start를 구현하는 두 가지 실용적인 방법을 소개하며, 각 방법은 STM32CubeMX로 생성한 기본 설정에 쉽게 통합할 수 있습니다
방법 1: 소프트웨어 기반 Soft Start
이 방법은 메인 루프에서 듀티 사이클(duty cycle)을 점진적으로 증가시키는 간단한 방식입니다.초보자에게 적합하며, 추가 하드웨어 없이 구현 가능합니다
구현 단계
- 타이머 PWM 설정 : STM32의 타이머(예: TIM1)를 PWM 모드로 설정
- Soft Start 로직: 듀티 사이클을 0에서 시작해 일정 간격(예: 10ms)으로 증가
- 타이밍 제어 : HAL_Delay()로 간격을 제어(테스트용)
예제 코드
#include "stm32f4xx_hal.h"
TIM_HandleTypeDef htim1; // PWM을 생성할 타이머 핸들 (Timer handle for generating PWM)
// 함수 선언 (Function declarations)
void SystemClock_Config(void); // 시스템 클럭 설정 (System clock configuration)
void MX_GPIO_Init(void); // GPIO 초기화 (GPIO initialization)
void MX_TIM1_Init(void); // 타이머 1 초기화 (Timer 1 initialization)
int main(void) {
HAL_Init(); // HAL 라이브러리 초기화 (Initialize HAL library)
SystemClock_Config(); // 시스템 클럭 설정 (Configure system clock, generated by STM32CubeMX)
MX_GPIO_Init(); // GPIO 설정 (Configure GPIO)
MX_TIM1_Init(); // PWM 타이머 설정 (Configure PWM timer)
// PWM 신호 출력 시작 (TIM1, 채널 1) (Start PWM signal output on TIM1, Channel 1)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
uint32_t duty_cycle = 0; // 초기 듀티 사이클 (0%) (Initial duty cycle, 0%)
const uint32_t max_duty = 1000; // 최대 듀티 사이클 (ARR=1000, 100%) (Maximum duty cycle, ARR=1000, 100%)
const uint32_t increment = 10; // 한 번에 증가할 듀티 사이클 값 (Duty cycle increment per step)
const uint32_t delay_ms = 10; // 증가 간격 (10ms) (Interval between increments, 10ms)
// Soft Start: 듀티 사이클을 점진적으로 증가 (Soft Start: Gradually increase duty cycle)
while (duty_cycle < max_duty) {
// TIM1 채널 1의 CCR 레지스터에 듀티 사이클 값 설정 (Set duty cycle in TIM1 Channel 1 CCR register)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty_cycle);
duty_cycle += increment; // 듀티 사이클 증가 (Increase duty cycle)
if (duty_cycle > max_duty) duty_cycle = max_duty; // 최대값 제한 (Limit to maximum duty cycle)
HAL_Delay(delay_ms); // 10ms 대기 (Soft Start 속도 조절) (Wait 10ms to control Soft Start speed)
}
// Soft Start 완료 후 목표 듀티 사이클 유지 (Maintain target duty cycle after Soft Start)
while (1) {
// 추가 제어 로직 (예: 사용자 입력 처리) (Additional control logic, e.g., handle user input)
}
}
void MX_TIM1_Init(void) {
TIM_OC_InitTypeDef sConfigOC = {0}; // 출력 비교(OC) 설정 구조체 (Output Compare configuration structure)
// TIM1 기본 설정 (TIM1 basic configuration)
htim1.Instance = TIM1; // 타이머 1 선택 (Select Timer 1)
htim1.Init.Prescaler = 0; // 프리스케일러 (클럭 분주 없음) (Prescaler, no clock division)
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 업 카운터 모드 (Up-counter mode)
htim1.Init.Period = 1000; // ARR 값 (PWM 주기, 1000=100%) (ARR value, PWM period, 1000=100%)
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 클럭 분주 비활성화 (Clock division disabled)
HAL_TIM_PWM_Init(&htim1); // PWM 모드로 타이머 초기화 (Initialize timer in PWM mode)
// PWM 채널 설정 (채널 1) (PWM channel configuration, Channel 1)
sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM 모드 1 설정 (Set PWM mode 1)
sConfigOC.Pulse = 0; // 초기 듀티 사이클 0 (CCR1 값) (Initial duty cycle 0, CCR1 value)
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 출력 극성: High (Output polarity: High)
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 빠른 모드 비활성화 (Fast mode disabled)
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); // 채널 1에 설정 적용 (Apply settings to Channel 1)
}
방법 2: 타이머 인터럽트를 이용한 Soft Start
타이머 인터럽트(Timer interrupt)를 사용하면 메인 루프를 차단하지 않고 Soft Start를 구현할 수 있습니다. 실시간 시스템에 적합하며, 주기적인 듀티 사이클 업데이트를 자동화합니다
구현 단계
- PWM 타이머 설정 : TIM1을 PWM 모드로 설정
- 인터럽트 타이머 설정 : TIM2를 사용해 10ms마다 인터럽트 발생
- 인터럽트 핸들러 : 듀티 사이클을 증가시키고 목표값 도달 시 인터럽트 비활성화
예제 코드
#include "stm32f4xx_hal.h"
TIM_HandleTypeDef htim1; // PWM용 타이머 핸들 (Timer handle for PWM)
TIM_HandleTypeDef htim2; // Soft Start용 인터럽트 타이머 핸들 (Timer handle for Soft Start interrupt)
// 함수 선언 (Function declarations)
void SystemClock_Config(void); // 시스템 클럭 설정 (System clock configuration)
void MX_GPIO_Init(void); // GPIO 초기화 (GPIO initialization)
void MX_TIM1_Init(void); // PWM 타이머 초기화 (PWM timer initialization)
void MX_TIM2_Init(void); // 인터럽트 타이머 초기화 (Interrupt timer initialization)
// Soft Start 변수 (Soft Start variables)
uint32_t duty_cycle = 0; // 현재 듀티 사이클 (0%) (Current duty cycle, 0%)
const uint32_t max_duty = 1000; // 최대 듀티 사이클 (ARR=1000, 100%) (Maximum duty cycle, ARR=1000, 100%)
const uint32_t increment = 10; // 한 번에 증가할 듀티 사이클 값 (Duty cycle increment per step)
int main(void) {
HAL_Init(); // HAL 라이브러리 초기화 (Initialize HAL library)
SystemClock_Config(); // 시스템 클럭 설정 (Configure system clock)
MX_GPIO_Init(); // GPIO 설정 (Configure GPIO)
MX_TIM1_Init(); // PWM 타이머 설정 (Configure PWM timer)
MX_TIM2_Init(); // 인터럽트 타이머 설정 (Configure interrupt timer)
// PWM 신호 출력 시작 (TIM1, 채널 1) (Start PWM signal output on TIM1, Channel 1)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// Soft Start용 인터럽트 타이머 시작 (Start interrupt timer for Soft Start)
HAL_TIM_Base_Start_IT(&htim2);
while (1) {
// 메인 루프에서 다른 작업 수행 가능 (Perform other tasks in the main loop)
}
}
void MX_TIM1_Init(void) {
TIM_OC_InitTypeDef sConfigOC = {0}; // 출력 비교 설정 구조체 (Output Compare configuration structure)
// TIM1 기본 설정 (PWM용) (TIM1 basic configuration for PWM)
htim1.Instance = TIM1; // 타이머 1 선택 (Select Timer 1)
htim1.Init.Prescaler = 0; // 프리스케일러 (클럭 분주 없음) (Prescaler, no clock division)
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 업 카운터 모드 (Up-counter mode)
htim1.Init.Period = 1000; // ARR 값 (PWM 주기 설정) (ARR value, sets PWM period)
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 클럭 분주 비활성화 (Clock division disabled)
HAL_TIM_PWM_Init(&htim1); // PWM 모드로 타이머 초기화 (Initialize timer in PWM mode)
// PWM 채널 설정 (채널 1) (PWM channel configuration, Channel 1)
sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM 모드 1 설정 (Set PWM mode 1)
sConfigOC.Pulse = 0; // 초기 듀티 사이클 0 (CCR1 값) (Initial duty cycle 0, CCR1 value)
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 출력 극성: High (Output polarity: High)
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 빠른 모드 비활성화 (Fast mode disabled)
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); // 채널 1에 설정 적용 (Apply settings to Channel 1)
}
void MX_TIM2_Init(void) {
// TIM2 기본 설정 (인터럽트용) (TIM2 basic configuration for interrupts)
htim2.Instance = TIM2; // 타이머 2 선택 (Select Timer 2)
htim2.Init.Prescaler = 8399; // 프리스케일러 (84MHz에서 10ms 주기 생성) (Prescaler, generates 10ms period at 84MHz)
htim2.Init.Period = 9999; // 인터럽트 주기 (10ms) (Interrupt period, 10ms)
htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 업 카운터 모드 (Up-counter mode)
HAL_TIM_Base_Init(&htim2); // 기본 타이머 모드로 초기화 (Initialize in basic timer mode)
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
// 타이머 인터럽트 콜백 함수 (Timer interrupt callback function)
if (htim->Instance == TIM2) { // TIM2 인터럽트인지 확인 (Check if it’s a TIM2 interrupt)
if (duty_cycle < max_duty) { // 목표 듀티 사이클에 도달하지 않은 경우 (If target duty cycle not reached)
duty_cycle += increment; // 듀티 사이클 증가 (Increase duty cycle)
if (duty_cycle > max_duty) duty_cycle = max_duty; // 최대값 제한 (Limit to maximum duty cycle)
// TIM1 채널 1의 CCR 레지스터에 듀티 사이클 값 설정 (Set duty cycle in TIM1 Channel 1 CCR register)
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty_cycle);
} else {
// 목표 듀티 사이클 도달 시 인터럽트 비활성화 (Disable interrupt when target duty cycle is reached)
HAL_TIM_Base_Deactivate(&htim2);
}
}
}
Soft Start 설정 팁
- 타이밍 조정 :
- Soft Start 시간: 모터는 100ms–1s for motors, 500ms–2s for LEDs 로 설정
- increment와 delay_ms(또는 인터럽트 주기)를 조정해 부드러운 변화 구현
- PWM 주파수 :
- 모터: 1kHz~20kHz (Motors: 1kHz–20kHz)
- LED: 100Hz~1kHz (LEDs: 100Hz–1kHz)
- STM32CubeMX에서 Prescaler와 Period로 주파수 설정
- 부하 특성 :
- 모터: 과전류 방지를 위해 전류 피드백 모니터링
- LED: 로그 스케일로 듀티 사이클 증가 시 자연스러운 밝기 변화
- STM32CubeMX 활용 :
- STM32CubeMX로 타이머 설정을 생성해 초기화 오류 최소화
- 예: TIM1을 PWM 모드로, TIM2를 기본 타이머로 설정
디버깅 및 테스트
- 오실로스코프 : PWM 핀의 듀티 사이클 증가 확인
- UART 디버깅 : 듀티 사이클 값을 시리얼로 출력
- STM32 모델 : STM32F4, STM32G4 등 모델별 레지스터 차이 확인 models like STM32F4, STM32G4).
결론
STM32 PWM Soft Start는 모터, LED, 전원 제어에서 시스템 안정성을 높이는 필수 기술입니다. 소프트웨어 기반 방식은 간단하고, 타이머 인터럽트 방식은 실시간 제어에 적합합니다. .
'MCU > STM32' 카테고리의 다른 글
STM32CubeMX에서 아두이노 스타일 사용자 코드 구조 만들기 (0) | 2025.09.14 |
---|---|
ADXL345 가속도 센서 STM32 HAL 라이브러리 드라이버 코드 구현 (0) | 2025.08.24 |
STM32 ADC 샘플 타임 설정 방법과 실무 팁 (0) | 2025.08.21 |
STM32 링커 스크립트: 상세 설명, 구조, 작성 방법 및 예제 (STM32 Linker Script: Detailed Explanation, Structure, Writing Methods, and Examples) (4) | 2025.08.18 |
STM32로 Modbus RTU Slave 코드 구현: DMA와 저전력 최적화 (0) | 2025.08.13 |
STM32G474 를 이용한 동일 어드레스를 갖는 64채널 I2C 디바이스 제어 (0) | 2025.08.12 |
STM32H503RB I3C 통신 코드 구현: 초보자를 위한 상세 가이드 (0) | 2025.08.10 |