관리 메뉴

거북이처럼 천천히

8bit Timer / counter - Fast PWM Mode 본문

Embedded Programming (AVR)/Atmega 128A (실습)

8bit Timer / counter - Fast PWM Mode

유로 청년 2024. 6. 4. 20:08

서론 

 

이전 게시글에서는 CTC Mode ( Clear Timer on Compare Match ) Mode와 Normal Mode에 대해서 다양한 파형을 만들어 봄으로서 공부하였고, 이번에는 duty ratio를 컨트롤 할 수 있는 Fast PWM Mode에 대해서 살펴보도록 하겠다.

 

 

 

본론 (Fast PWM  Mode에 대한 이론)

💡 Q) Fast PWM Mode란 무엇인가?

 

이전에 살펴보았던 CTC Mode와 Normal Mode에 대해서 정리하면 다음과 같다.

 

CTC (Clear Timer on Compare Match) Mode

  • OCRn (Output Compare Register n) 을 설정해줌으로서 Counter가 카운트한 값(TCNT0)이 OCRn 값과 Match가 되면 Output Compare Match Interrupt를 발생시키게 되고, 이를 TIFR (Timer/Counter Interrupt Flag Register) Register의 OCF0 비트 자리 값이 0에서 1로 변환된다.
  • 즉, CTC Mode는 OCRn (Output Compare Register n) 값을 통해 Counter가 카운트하는 값을 컨트롤한다.
  • 또한 CTC Mode는 8bit Timer/Counter인 경우에 정해진 핀 자리에서만 생성된 파형을 출력시킬 수 있다.
    → 8bit Timer/Counter 0 : PB4 (OC0)
    → 8bit Timer/Counter 2 : PB7 (OC2)

 

Normal Mode

  • CTC Mode와 달리 초기 설정 과정에서 TCNTn(Timer/Counter Register n) 값을 직접 대입함으로서 Counter가 0부터 카운트하는 것이 아닌 특정 값에서부터 카운트를 하기 시작한다.
  • 또한 CTC Mode와 달리 OCRn (Output Compare Register n) 값이 없기 때문에 Counter는 Max까지 카운트하며, Max값과 Match가 되면 Overflow Interrupt를 발생한다.
  • Overflow Interrupt로 인해 초기 설정 값(= TCNTn 값)이 초기화 되었기 때문에 다시 TCNTn 값을 대입하여 재새팅한다.
  • Normal Mode는 CTC Mode와 Fast PWM Mode와 달리 꼭 정해진 핀 (OC0, OC2)에서 출력할 필요 없이 원하는 핀에서 출력하도록 설정이 가능하다.
  • 단, ATmega 128 입장에서는 어떤 핀이 파형 출력을 위한 핀인지 모르기 때문에 출력으로 설정한 모든 핀에서 파형이출력된다, 따라서 목적에 맞게 Normal Mode를 사용하는 것이 중요하다. 

 

Fast PWM Mode는 OCRn (Output Compare Register n)값을 설정함으로서 TCNTn 값이 OCRn 값과 Match돠면 Output Compare Match Interrupt가 발생하지만, Counter는 0으로 초기화 되는 것이 아닌 계속 카운트 하여 MAX값과 match되면 한 번 더 Overflow Interrupt를 발생시킨 뒤, TCNTn 값이 0으로 초기화 된다.

 

즉, Fast PWM Mode는 두 번의 Interrupt (= Output Compare Match Interrupt와 Overflow Interrupt)를 발생하며, 두 번의 Interrupt에 대해서 OCn(= Output Compare signal)은 Toggle을 발생 시킨다.

 

 

 

위 내용에 대해서 Time diagram으로 표현하면 다음과 같다.

8bit Timer/Counter의 Fast PWM Mode의 Time diagram

 

 

위 Time diagram을 통해 다음 정보를 얻을 수 있다.

  • Fast PWM Mode에서는 두 번의 Interrupt가 발생한다.
  • Output Compare Match Interrupt가 발생하여도 Counter는 Max 값과 Match 될 때까지 계속 카운트한다.
  • 두 번의 Interrupt에 대해서 OCn 신호는 Toggle을 발생 시킨다.
  • OCRn (Output Compare Register n) 값을 조절함으로서 이전에 다루었던 CTC Mode나 Normal Mode와 달리 duty ratio를 제어할 수 있다.

 

 

 

     

Q) 그럼 두 번의 Interrupt가 발생하기 때문에 TIFR (Timer/Counter Interrupt Flag Register)를 두 번 감지 및 초기화 작업을 수행해야 하는가?

 

A) 놉! TIFR (Timer/Counter Interrupt Flag Register)는 CTC Mode나 Normal Mode에서만 동작 및 필요로 하지 Fast PWM Mode에서는 동작하지 않으며, 따라서 TIFR Register를 사용할 필요, 감지 및 초기화 작업을 해줄 필요가 없다.

 

 

 

 

본론 (CTC Mode에 대한 실습)

 

이번에는 8bit Timer/Counter과 Fast PWM Mode를 이용하여 ATmega 128A의 기본 클럭 주파수 16MHz를 128 분주시켜 976.5625Hz를 갖는 새로운 파형을 출력시킬 것이며, duty ratio를 50%가 되도록 설계할 것이다.

 

● 8bit Timer/Counter + Fast PWM Mode
● Prescaler : 128
● 새로운 파형의 주파수 : 975.5625Hz
● Duty ratio : 50%

 

 

 

📌 1단계) 8bit Timer/Counter에는 Timer/Counter 0/2가 있는데, 어떤 것을 사용할 것인가?

 

출력핀을 OC0 (PORT B의 4핀, PB4)로 설정하겠다.

 

 

 

 

📌 2단계) 분주비 (Prescaler, N)을 설정

 

Fast PWM Mode 에서 fclk와 focn과의 관계는 다음과 같다.

 

 

위 공식에 의해 N (Prescaler)를 구하면 다음과 같다.

 

 

따라서 ATmeaga 128A의 기본 클럭 주파수 16000000Hz 를 128분주 하면 975.5625Hz 주파수를 갖는 파형을 생성 할 수 있다. 따라 이를 토대로 다시 정리 하면 다음과 같다.

 

● 8bit Timer/Counter + Fast PWM Mode
● Prescaler : 128
● 새로운 파형의 주파수 : 975.5625Hz
● Duty ratio : 50%

 

 

 

 

📌  3단계) TCCRn (Timer/Counter Control Register n)을 설정

 

TCCR0 (Timer / Counter Control Register 0)

 

● WGM01, WGM00 (Waveform Generation Mode) : 1, 1
● COM01, COM00 (Compare Output Mode, Fast PWM Mode) : 1, 0
● CS02, CS01, CS00 (Clock Select Bit) : 1, 0, 1

 

 

 

 

📌  4단계) Duty ratio를 정하고, 그에 따른 OCRn (Output Compare Register n)를 정한다.

 

이번 구현에서는 Duty ratio를 50%로 정했기 때문에 그에 따른 OCRn 값은 다음과 같다. 

 

하지만, 만약 Duty ratio를 25%, 75%로 정했다면 그에 따른 OCRn 값은 다음과 같다.

 

 

 

 

 

본론 (Source Code)

 

     

아래 소스 코드는 본인이 TIFR (Timer/Counter Interrupt Flag Register)가 Fast PWM Mode에서 동작하지 않는다는 사실을 모르는 상태에서 작성했던 소스 코드이다. 따라서 while(1) 안에 작성했던 TIFR (Timer / Counter Interrupt Flag Register)에 관한 초기화 및 Flag 감지에 관한 코드들을 무의미하다. 

 

따라서 아래의 코드는 비효율적이기 때문에 "이렇게 생각했었구나."라고 생각하고, 넘어갈 것.

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Main method
int main(void) {
	// CTC Mode 와 Fast PWM Mode 은 8bit timer/counter를 사용할 경우
	// 8bit Timer/Counter 0 : PB4
	// 8bit Timer/Counter 2 : PB7
	// 
	// 하지만, Normal Mode는 경우 위 제한 조건에 해당 되지 않기 때문에
	// 원하는 핀에 출력하도록 만들 수 있지만, 단, 출력으로 설정된 모든 핀에서
	// 파형이 출력 되기 때문에 이를 고려하여 사용
	DDRB |= (1<<DDB4);
	
	// PB4의 초기 출력 설정
	// 
	// 이번에는 non-inverting mode를 사용했기 때문에
	// Output Compare Match Interrput 에서는 Clear OC0 가 발생하고,
	// Overflow Interrupt 에서는 Set OC0 가 발생한다.
	PORTB |= (1<<PORTB4);
	
	// TCCR0 = Timer/Counter Control Register 0 
	// Compare Output Mode : non-inverting mode
	// Prescaler = 64
	TCCR0 |= (1<<WGM01 | 1<<WGM00 | 1<<CS02 | 1<<COM01);
	
	OCR0 = 128;
	
	while(1) {
		// Output Compare Match Interrupt 가 발생하면
		while((TIFR & (1<<OCF0))==0);
		
		// Timer/Counter Interrupt Flag Register 에서 
		// Output Compare Match Interrupt 의 Flag 를 초기화
		TIFR |= (1<<OCF0);
		
		// Overflow Interrupt 가 발생하면
		while((TIFR & (1<<TOV0))==0);
		
		// Timer/Counter Interrupt Flag Register 에서 
		// Overflow Interrupt 의 Flag 를 초기화
		TIFR |= (1<<TOV0);
		
		// Interrupt 들에 의해 초기 세팅 리셋되었기 때문에 재새팅
		OCR0 = 128;
	}
}

 

 

 

그래서 위 코드에서 TIFR Register에 관한 코드를 제거하고, 코드를 다시 작성하면 다음과 같다.

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Main method
int main(void) {
	// CTC Mode 와 Fast PWM Mode 은 8bit timer/counter를 사용할 경우
	// 8bit Timer/Counter 0 : PB4
	// 8bit Timer/Counter 2 : PB7
	// 
	// 하지만, Normal Mode는 경우 위 제한 조건에 해당 되지 않기 때문에
	// 원하는 핀에 출력하도록 만들 수 있지만, 단, 출력으로 설정된 모든 핀에서
	// 파형이 출력 되기 때문에 이를 고려하여 사용
	DDRB |= (1<<DDB4);
	
	// PB4의 초기 출력 설정
	// 
	// 이번에는 non-inverting mode를 사용했기 때문에
	// Output Compare Match Interrput 에서는 Clear OC0 가 발생하고,
	// Overflow Interrupt 에서는 Set OC0 가 발생한다.
	PORTB |= (1<<PORTB4);
	
	// TCCR0 = Timer/Counter Control Register 0 
	// Compare Output Mode : non-inverting mode
	// Prescaler = 64
	TCCR0 |= (1<<WGM01 | 1<<WGM00 | 1<<CS02 | 1<<COM01);
	
	// Duty ratio = 50% 를 생성하기 위해 
	// 이에 따른 OCR0 (Output Compare Register 0)의 값을 128로 설정
	OCR0 = 128;
	
	while(1) {
	}
}

Duty ratio : 50%인 경우의 파형이며, 전압의 한 눈금의 크기가 2V이기 때문에 출력 파형의 전압의 크기는 5V이다.
Duty ratio : 25%인 경우의 파형이며, 이 역시 한 눈금의 크기가 2V이기 때문에 출력 파형의 전압 크기는 5V임을 확인 가능하다.

 

 

 

 

 

정리

지금까지 공부했던 CTC Mode, Normal Mode, Fast PWM Mode에 대해서 정리하면 다음과 같다.

 

1) CTC Mode

  • OCRn (Output Compare Register n) Register 의 값을 설정함으로서 Counter가 카운트할 수 있는 값을 제한한다.
  • TCNTn (Timer/Counter Register n) 값이 OCRn과 Match가 되면 Output Compare Match Interrupt가 발생한다.
  • TIFR (Timer/Counter Interrupt Flag Register)의 OCF0 비트 값이 0->1로 변환되게 된다.
  • Output Compare Match Interrupt가 발생하면 TCNTn 값이 0으로 초기화한 후, 다시 카운트한다.

 

2) Normal Mode

  • 초기 설정으로 TCNTn(Timer/Counter Register n)값을 특정 값으로 설정하면 Counter는 0이 아닌 특정 값부터 카운트를 시작하게 되며, 따라서 Counter가 카우트할 수 있는 값을 제한 할 수 있다.
  • TCNTn (Timer/Counter Register n) 값이 MAX 값과 Match가 되면 Overflow Interrupt가 발생한다.
  • TIFR (Timer/Counter Interrupt Flag Register)의 TOV0 비트 값이 0->1로 변환하게 된다.
  • Overflow Interrupt가 발생하면 TCNTn 값이 0으로 떨어지지만, TCNTn 값 재설정을 통해 특정 값에서 다시 시작한다.

 

3) Fast PWM Mode

  • 초기 설정으로 OCRn (Output Compare Register n) Register 의 값을 설정하지만, TCNTn (Timer/Counter Register n) Register 값이 OCRn 값에 Match가 되어 Output Comapre Match Interrupt 발생할 뿐, TCNTn (Timer/Counter Register n)값은 계속 카운트하며, MAX 값과 Match 되야 Overflow Interrupt를 발생시키고, 다시 TCNTn이 0으로 초기화된다.
  • Fast PWM Mode 에서는 TIFR (Timer/Counter Interrupt Flag Register)가 동작하지 않는다.
  • Fast PWM Mode는 CTC Mode와 Normal Mode와 달리 OCRn (Output Compare Register n)를 통해 출력 신호의 duty ratio를 컨트롤 할 수 있다.