거북이처럼 천천히

8bit Timer / counter - CTC Mode 본문

Embedded Programming/Atmega 128A (실습)

8bit Timer / counter - CTC Mode

유로 청년 2024. 6. 2. 17:07

서론 

 

 이번 게시글부터 8bit Timer / Counter와 ATmega 128A의 클럭 신호 (16MHz)을 이용하여 다양한 신호를 출력해 볼 것이다. 이를 통해 CTC Mode, Normal Mode, Fast PWM Mode 등 다양한 파형 발생모드 (Waveform Generation Mode)에 대해서 공부할 것이며, 이에 따른 발생할 수 있는 Interrupt와 분주비 설정에 따른 출력 신호의 주파수 변화에 대해서 알아볼 예정이다. 

 

 먼저, CTC Mode를 활용한 다양한 신호를 출력함으로서 CTC Mode에 대해서 공부해 보도록 하겠다.

 

 

본론 (CTC Mode에 대한 이론)

 

Q) CTC Mode란 무엇인가?

 

A) CTC Mode는 Clear Time on Compare Match Mode의 약자로 Counter가 카운트한 값(TCNT, Timer / Counter Register)이 Counter의 상한값인 OCR(Output Compare Register)와 일치하였을 때, Interrupt를 발생시키는 모드이다. 또한 Interrupt를 발생시킨 후, 다시 Counter의 카운트 값을 0으로 자동 초기화된 뒤, 다시 0부터 카운트한다.

 

 이때, 발생한 Interrupt를 Output compare match interrupt라고 하며, Output Compare Match Interrupt를 발생했음을 Regseiter 값을 통해 알려주게 되는데, 이 Register가 "TIFR, Timer/Counter Flag Regsiter"이다.

 

위 과정을 그림을 통해 설명하면 다음과 같다.

8bit Timer/Counter의 CTC Mode.

 

TCCR (Timer / Counter Control Register)
Compare Output Mode, Counter에서 Interrupt 발생시 (= compare match event 발생 시) 출력 동작을 어떻게 제어 할 것인지에 대한 것을 정하는 값이다.
Prescaler 설정값, ATmega 128의 기본 클럭 신호를 몇 개의 주기를 하나의 묶음으로 묶을 것인가를 정하는 요소
8bit timer/counter에서 어떤 파형 발생 모드(waveform Generation Mode)를 설정

 

첫 번째 그림에서 보는 바와 같이 Counter가 카운트한 값(TCNTn)이 OCR(Output Compare Register)를 만나게 되면 Output Compare match interrupt를 발생 시키면서 출력 신호(OCn, Output Compare n)가 Compare Output Mode 설정에 따라 반응하게 된다.

 

 

 

 

 

본론 (CTC Mode에 대한 실습)

 

이번에는 ATmega 128의 기본 클럭 주파수와 8bit timer/Counter, CTC Mode를 이용하여 1kHz의 주파수를 갖는 출력 신호를 갖도록 하겠으며, 특히 초기 출력 신호를 0으로 세팅한 뒤, Output Compare Match Interrupt가 발생하면 Toggle이 발생하도록 설계하겠다.

 

●  ATmega 128의 기본 클럭 주파수 (16MHz), 8bit Timer/Counter, CTC Mode 활용
●  출력 신호는 1kHz 주파수를 갖는다.
●  Output Compare Match Interrupt가 발생시 출력 신호에서 Toggle 발생

 

 

 

 

 

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

 

 

둘의 차이점은 Timer/Counter 0은 분주비의 값으로 1, 8, 32, 64, 128, 256, 1024 이 설정 가능

                        Timer/Counter 2은 분주비의 값으로 1, 8, 64, 256, 1024 이 설정 가능

 

Timer/Counter 0가 Timer/Counter 2보다 더 많은 분주비를 제공해주기 때문에 Timer/Counter 0를 사용할 것이며, 이에 따라 아래의 그림과 같이 Timer/Counter 0를 통해 생성된 새로운 출력 신호는 PORT B의 4핀에서 출력되게 된다.

 

Pin Configurations에 따라 OC0는 PB4에 위치해 있기 때문에 8bit Timer/Counter 0을 이용하여 새로운 신호를 생성하게 되면 PB4에서 출력이 나오게 된다.

 

 

 

 

 

📌  2단계) Prescaler (분주비, N)과 OCRn (Output Compare Register n)을 설정

 

 

아래의 관계식을 통해 Prescaler, OCRn 값을 정할 필요가 있다. 


 분주비 (Prescaler, N)인 경우에는 Timer/Counter 0를 사용했기 때문에 1, 8, 32, 64, 128, 256, 1024 값을 사용 가능하며, OCRn (Output Compare Regsiter n)인 경우에는 0에서 부터 Counter가 count할 수 있는 Max값인 255까지의 값을 가질 수 있다.

 

8bit Timer/Counter의 CTC Mode에서 클럭 신호와 Output Compare 신호의 주파수에 관한 관계식

 

 

 

 if) Prescaler(N)값을 64으로 설정하면 위 관게식에 의해 OCRn (Output Compare Register n)은 125를 갖게된다.

 

●  ATmega 128의 클럭 주파수 = 16MHz
●  OCn (Output Compare n)의 주파수 = 1kHz
●  N (Prescaler, 분주비) = 64
●  OCRn (Ouput Compare Register n) = 124

즉, OCRn (= Counter의 Top 값, Compare match interrupt가 발생하는 지점)이 125이기 때문에 TCNTn 값이 125을 만나게 되면 Interrupt가 발생하고, 이로 인해 OCn(Output Compare n) 신호가 Interrupt에 반응하게 된다

 

 

 

 

 

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

 

TCCRn 레지스터는 Compare Output Mode, Prescaler, Waveform Generation Mode를 설정할 수 있다.

 

TCCR (Timer / Counter Control Register)

 

● FOC0 : PWM(Pulse Width Modulation)이외의 모드에서 사용할 수 있다. 
                FOC0 비트가 세트되면 비교일치가 발생한 것과 동일한 효과가 파형 출력 핀 OC0 핀으로
               이루어진다. FOC0 비트 세트는 일회성으로 필요할 때마다 1로 설정해 주어야 한다. 

● WGM01, WGM00 : Waveform Generation Mode 
● COM01, COM00 : Compare Output Mode (Interrupt 발생시 출력을 어떻게 제어할 것인지 여부)
● CS00, CS01 : Clock Select (Prescaler 설정)

 

 

위 관계식을 통해 얻은 값들을 통해 TCCR0 Register의 값을 정하면 다음과 같다. 

TCCR0 Register = 0b0110 0100

 

 

 

📌  4단계) Output Compare Match Interrupt가 발생시 주의 사항

 

주의 사항 1) Interrupt가 발생하면 초기 세팅 값들이 사라진다.

 

초기 세팅하는 과정에서 OCRn (Output Compare Register n) 값을 125로 설정했지만, TCNT0 값이 OCRn값을 만나 Output Compare Match Interrupt가 발생하면 TCNT0 값이 0로 돌아가는 동시에 세팅 값이 사라지게 된다. 따라서 Output Compare Match Interrupt가 발생한 이후에 또 다시 OCRn 값을 재설정 해줘야 한다.

 

 

주의 사항 2) TIFR (Timer/Counter Interrupt Flag Register) 가 초기화 되었는지 여부를 확인하기.

 

TCNTn 값이 Max값을 만나 Overflow Interrupt가 발생하거나 OCRn값을 만나 Output Compare Match Interrupt가 발생하면 TIFR (Timer/Counter Interrupt Flag Register)를 통해 알리게 된다.

 

TIFR (Timer/Counter Interrupt Flag Register)

 

● OCF0 : Output Compare Match Interrupt가 발생하면 0에서 1로 변환
● TOV0 : Overflow Interrupt가 발생하면 0에서 1로 변환

 

 

Interrupt가 발생하면 이를 초기화 작업을 해줘야 하는데, 초기화 하는 방법에는 크게 2가지 방법이 있다.

  • ISR (Interrupt Service Routine)을 정의해서 Interrupt가 발생하면 자동적으로 ISR로 넘어가도록 함으로서
    자동적으로 초기화할 수 있다.
  • 해당 비트 위치에 1이라는 값을 직접 대입 함으로서 수동적으로 초기화할 수 있다.

 

만약 초기화 하지 않고, 계속 카운터를 할 경우 Interrupt가 발생했음에도 출력 신호에 변함없는 현상이 발생한다.

 

 

 

 

본론 (Source Code)

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

int main(void) {
	// PB4을 출력으로 설정
	DDRB |= (1<<DDRB4);
	
	// TCCR0 (Timer/Counter Control Register 0) 설정
	// OC0 (Output Compare) 신호는 1kHz를 설정
	// Prescaler, N을 64분주로 설정
	// Compare Output Mode = Output Compare Match Interrupt 발생시 출력 신호 제어
	//                     = Toggle 발생
	// Wavefrom Generation Mode = CTC Mode
	// TCCR0 = 0b0110 0100
	TCCR0 |= (1<<WGM01 | 1<<COM00 | 1<<CS02);
	
	// OCR0 = Output Compare Register
	OCR0 = 124;
	
	while(1) {
		// TIFR Register에서 OCF0 값이 0->1 변하면 
		// Output Compare Match Interrupt 발생했다는 Flag
		if((TIFR & (1<<OCF0))==0);
		
		// ISR(Interrupt Service Routine)을 구현하지 않았기 때문에
		// OCF0 위치에 1을 대입함으로서 수동 초기화
		TIFR |= (1<<OCF0);
		
		// Output Compare Match Interrupt가 발생했기 때문에 
		// 세팅값이 초기화가 되고, 이로 인해 세팅값 재설정 
		OCR0 = 124;
	} 
}

 

 

  • Oscilloscope를 통해 확인한 결과, 예상했던 바와 같이 1.00005kHz 주파수를 갖는 출력 신호를 확인할 수 있었고, 
    Output Compare Match Interrupt가 발생할 때, 출력신호가 Toggle되는 것까지 확인할 수 있었다.
  • 한 눈금 당 5V이기 때문에 출력 신호의 1의 값이 5V인 점도 확인할 수 있었다.

 

결론

 

8bit timer/Counter을 사용하여 CTC Mode에서 ATmega 128의 클럭 주파수 (16MHz) 을 통해 1kHz 주파수를 갖는 출력 신호를 생성했다. 비록, 알아야 할 개념도 많고, 계산도 이전보다 복잡하지만, 이를 통해 LED, 모터 제어를 할 수 있어 중요한 개념이기 때문에 반드시 이해하고 넘어가자.