모터 위상을 조절할 때 좋은 기술 : 이전 Fast PWM 은 증가하는 경우만 구현 가능했다

Dual - Slope Operation : 카운터가 증가와 감소 하는 방식 그래서 주파수가 Fast PWM 보다 느리다
Fast PWM vs Phase Correct PWM
| 구분 | Fast PWM | Phase Correct PWM |
| 카운터 동작 | 0 → 255 → 0 (상승만, 한 방향) | 0 → 255 → 0 (상승 후 하강, 양방향) |
| 작동 방식 | Single-Slope | Dual-Slope |
| 주기(주파수) | 빠름 (같은 분주비 기준 약 2배 빠름) | 느림 (반 주파수 수준) |
| 파형 대칭성 | 비대칭 (한쪽으로 기울어진 sawtooth) | 대칭 (삼각형 모양, 중심 기준 좌우 대칭) |
| 응용 예시 | LED 밝기, 단순 PWM 출력 | 모터 제어, DAC(아날로그 제어) 등 정밀 응용 |
Phase Correct PWM은 Fast PWM보다 주파수는 낮지만,
파형이 대칭이어서 전류·토크 리플이 적고,
모터 제어나 정밀 제어용으로 훨씬 안정적이다.
#궁금점 Fast PWM도 OCR 잘 설정하면 대칭적으로 만들 수 있나?
리셋되는 시점이 문제입니다. 리셋 순간이 항상 하강 엣지에만 생긴다.
보통 중심이 되는 지점에 ISR 설정한다 참고
Phase Correct PWM LED ON OFF 실습
이전 실습과 레지스터 분석 유사

PWM phase correct : 0 0 1
COM0A : 1 0
#궁금점 : 비교일치 순간에 왜 Clear 로 하는가
분주비 1024 설정 : 101
계산식 : 16Mhz / (분주비 * 510) > 256 x
Code
#define F_CPU 16000000UL // CPU 클록 주파수 (16MHz)
#include <avr/io.h> // AVR 입출력 제어용 헤더
#include <avr/interrupt.h> // 인터럽트 관련 함수 사용
// 비트 세트(set bit) / 클리어(clear bit) 매크로
#define sbi(PORTX, BitX) (PORTX |= (1 << BitX))
#define cbi(PORTX, BitX) (PORTX &= ~(1 << BitX))
// ===============================
// Phase Correct PWM 초기화 함수
// ===============================
void Phase_Correct_PWM_Init(void)
{
cbi(SREG, 7); // 전역 인터럽트 비활성화 (설정 중엔 끔)
// -------- PWM 모드 설정 --------
// WGM02:0 = 0b001 → Phase Correct PWM (TOP=0xFF)
sbi(TCCR0A, WGM00); // WGM00 = 1
// WGM01, WGM02는 0으로 유지됨
// -------- 비교출력 모드 설정 --------
// COM0A1:0 = 10 → 비반전 모드 (up-count 시 Clear, down-count 시 Set)
sbi(TCCR0A, COM0A1);
// -------- 분주비 설정 --------
// CS02:0 = 0b101 → 분주비 1024 (속도 느림, LED 테스트용으로 적당)
sbi(TCCR0B, CS02);
sbi(TCCR0B, CS00);
// -------- 비교일치 인터럽트 허용 --------
// OCR0A 값과 TCNT0가 일치할 때 인터럽트 발생
sbi(TIMSK0, OCIE0A);
// -------- 출력 핀 설정 --------
// OC0A 핀 = PD6 (아두이노 기준으로 6번 핀)
sbi(DDRD, PD6); // PD6을 출력으로 설정
cbi(PORTD, PD6); // 초기값 LOW로 설정
// -------- 초기값 설정 --------
OCR0A = 0; // 비교일치 초기값 0
sbi(SREG, 7); // 전역 인터럽트 활성화
}
// ===============================
// Timer0 Compare Match A 인터럽트 서비스 루틴
// ===============================
ISR(TIMER0_COMPA_vect)
{
OCR0A += 1; // PWM 듀티 변경 (1씩 증가)
if (OCR0A == 255) // 최대 도달 시
{
OCR0A = 0; // 다시 0으로 (밝기 반복)
}
}
// ===============================
// 메인 함수
// ===============================
int main(void)
{
Phase_Correct_PWM_Init(); // PWM 초기화
while (1)
{
// 메인 루프: 인터럽트가 자동으로 PWM 듀티 변경 수행
}
}'Atmega328p' 카테고리의 다른 글
| {Atmega328p}-TWI (0) | 2025.10.31 |
|---|---|
| {Atmega328p}-SPI (1) | 2025.10.31 |
| {Atmega328p}-Fast PWM Mode (0) | 2025.10.29 |
| {Atmega328p}-Timer , Counter (0) | 2025.10.29 |
| {Atmega328p}-ADC (0) | 2025.10.26 |