거북이처럼 천천히

8bit timer/counter를 가지고 놀기 (1) 본문

Embedded Programming/Atmega 128A 이것저것

8bit timer/counter를 가지고 놀기 (1)

유로 청년 2024. 6. 16. 14:03

Verilog를 공부하면서 ATmega에 대한 감각과 지식을 점차 사라지는 것을 느꼈다....

 

그래서 Verilog 1차 정리를 다한 뒤, 8bit timer / counter 0, 2와 다양한 모드을 이용해 펄스파형을 출력하고,

관찰함으로서 ATmega 128의 timer/counter를 다시 정리 및 상기하도록 하겠다.

 

 

 

1. 8bit Timer / Counter 0 (CTC Mode)

환경) PB4(OC0)을 파형 출력핀으로 설정

 

  • Prescaler, N : 128
  • Output Compare Register 0, OCR0 : 174
  • Frequency of output compare 0 Signal, foc0 : 357.1428571Hz

equation about relation frequency of clock signal between frequency of output compare

 

 

 

설명) CTC Mode의 Time diagram은 다음과 같다.

8bit timer/counter 0의 CTC Mode

 

  • TCNT0 (8bit Timer/Counter Register 0)의 값이 0부터 시작해 1씩 counter를 한다.
  • TCNT0 가 OCR0 (Output Compare Register 0) 값과 Match가 되면 Output Compare Match Interrupt 를 발생
  • Output Compare Match Interrupt 를 발생 했음을 TIFR (Timer/Counter Interrupt Flag Register) Register를 이용하여 OCF0 (Output Compare Flag 0) 비트 값을 0→ 1 로 변경됨으로 알린다.
  • TCNT0 Register 값은 Output Compare Match Interrupt 를 발생시키고, 다시 초기화하여 0으로 돌아간 뒤, 0부터 다시 카운트를 시작한다.
  • TIFR (Timer/Counter Interrupt Flag Register) Register의 OCF0 (Output Compare Flag 0) 값을 초기화를 해줄 필요가 있는데, TIFR Register를 초기화해는 방법에는 크게 2가지 방법이 있다.
    ▶자동 초기화 : 해당 Interrupt가 발생시, 이에 대한 ISR (Interrupt Service Routine)을 구현해주었으며, 
                             ISR을 실행할 때, 자동적으로 초기화 된다.
    ▶수동 초기화 : TIFR (Timer/Counte Flag Register)에서 Interrupt가 발생했음을 나타냈던 Flag 위치에 
                             1값을 직접 대입해줌으로서 수동적으로 초기화 된다.
  • CTC (Clear Timer on Compare Match) Mode에서 출력 펄스파형의 duty ratio을 조절 할 수 없고, 항상 duty ratio가 50%인 파형이 출력된다.

 

코드)

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

// Function prototype
void init_Port ();

// Main method
int main(void)
{
	// 8bit timer/Counter 0를 이용할 경우, 
	// PB4(OC0)가 고정 출력 포트이기 때문에 이 점 유의.
    init_Port();
	
	// 8bit timer / counter 0 
	// N (prescaler, 분주비) = 128
	// OCR0 (Output Compare Match Register 0) = 174
	// fOC0 (Frequency of Output Compare 0 Signal) = 357.1428571Hz
	
	// Timer/Counter Control Register 0
	TCCR0 |= (1<<COM00 | 1<<CS02 | 1<<CS00 | 1<<WGM01);
	
	// Output compare match register 0
	OCR0 = 174;
	
    while (1) 
    {
		// TIFR : Timer/Counter Interrupt Flag Register
		while((TIFR & (1<<OCF0))==0);
		
		// Reset TIFR.
		TIFR |= (1<<OCF0);
		
		// Reset Output Control Register 0.
		OCR0 = 174;
    }
}

// Initialization of Port.
void init_Port () {
	DDRB = (1<<DDB4);
	PORTB &= ~(1<<PORTB4);
}

 

 

측정)

PB4(OC0)를 파형 출력 핀으로 설정

 

Oscilloscope를 통해 출력 파형의 주파수는 357.161Hz, 출력 파형의 전압 크기는 5V임을 확인

 

 

 

2. 8bit Timer / Counter 2 (Normal Mode)

환경) 

  • Prescaler, N = 64
  • Output Compare Signal 2, foc2 = 500Hz

Equation of relation between frequency of output compare signal and timer/counter register

 

 

설명) 

  • TCNT2 (Timer/Counter Register 2)는 0부터 카운트하는 것이 아닌 초기화된 값부터 카운트하기 시작한다.
  • 즉, CTC (Clear timer compare match) mode는 Counter의 Top인 OCR (Output Compare Register)를 정의함으로서 counter가 카운트할 수 있는 값을 제한하지만, Normal mode는 Counter의 Bottom인 TCNT (Timer/Counter Register) 를 정의함으로서 Counter가 카운트할 수 있는 값을 제한한다.
  • TCNT2 (Timer/Counter Register 2) 값이 8bit counter의 Max값인 255를 만나면 Overflow Interrupt를 발생
  • Overflow Interrupt가 발생하면 TIFR (Timer/Counter Interrupt Flag Register) 에서 TOV2 자리 값이 0 → 1로 변환하여 Overflow Interrupt가 발생했음을 나타낸다.
  • TCNT2 Register는 Max값을 만나 Overflow interrupt를 발생시키고, 다시 0으로 갔다가 0에서 특정값으로 다시 초기화된 뒤, 다시 1씩 카운트하기 시작한다.
  • Normal mode도 CTC mode와 동일하게 출력 펄스파형의 duty ratio는 50%으로 고정되어 있다.

 

코드)

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

int main(void)
{
	// Set PORTE5 as output
	DDRE |= (1<<DDE5);
	
	// Clear PORTE5 initially
	PORTE &= ~(1<<PORTE5);
	
	// TCCR2 = Timer/Counter Control Register 2
	// Prescaler, N = 64
	// TCNT2 = Timer/Counter Register 2 = 6
	TCCR2 |= (1<<CS21 | 1<<CS20);  // CS22 = 1, CS21 = 0, CS20 = 0
	
	// Set initial value for Timer/Counter 2 (TCNT2)
	TCNT2 = 6;
	
	while (1)
	{
		// Wait for overflow flag (TOV2) to be set
		while ((TIFR & (1<<TOV2)) == 0);
		
		// Toggle PORTE5 pin
		PORTE ^= (1<<PORTE5);
		
		// Clear TOV2 flag by writing 1 to it
		TIFR |= (1<<TOV2);
		
		// Initialize TCNT2
		TCNT2 = 6;
	}
}

 

측정)

 

PE5을 펄스파형의 출력핀으로 설정

 

Oscilloscope를 통해 PE5에서 발생한 펄스파형의 주파수는 500.026Hz이며, 전압의 크기는 5V임을 확인

 

 

 

 

3. 8bit Timer / Counter 0 (Fast PWM Mode)

환경) 

  • Prescaler, N = 256
  • Duty ratio of Pulse wave = 24%
  • Output compare register 0, OCR0 = 63
  • Output compare match interrupt 발생시, OC0가 Clear된다.
    즉, Non-inverting mode 설정

equation about relate between frequency of clock signal and frequency of output compare signal

 

설명) 

  • TCNT0 (Timer/Counter Register 0) 가 1씩 카운트하다가 OCR2 (Output compare register 2)와 Match하면 Output Compare Match Interrupt를 발생시킨다.
  • 하지만, CTC (Clear timer Compare Match) mode와 달리 0으로 초기화 되지 않고, 계속 카운트한다.
  • TCNT0 값이 8bit timer/counter의 Max 값과 Match되면 Overflow Interrupt를 발생시키고, 0으로 초기화된다.
  • 즉, Fast PWM mode는 두 번의 Interrupt를 발생시킨다.
  • Output Compare Match Interrupt와 Overflow Interrupt가 발생하면 OC0 signal의 값이 변하며, 각각 서로 다른 레벨로 Toggle된다.
  • Fast PWM Mode에서는 CTC Mode와 Normal Mode와 달리 TIFR (Timer/Counter Interrupt Flag Register) 값이 동작하지 않는다.

 

Timing Diagram of Fast PWM Mode

 

코드)

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

// substitute constant
#define PULSE_DDR		DDRB
#define PULSE_PORT		PORTB

// Function prototype.
void init_PORT();

// Main method
int main(void)
{
    init_PORT();
	
	// TCCR0 = 8bit Timer/Counter Register 0
	// Prescaler, N = 256
	// Output compare signal, foc0 = 244.140625Hz
	TCCR0 |= (1<<COM01 | 1<<CS02 | 1<<CS01 | 1<<WGM01 | 1<<WGM00);
	
	// initialize OCR0.
	// duty ratio = 24%
	OCR0 = 63;
	
    while (1) 
    {
    }
}

// Initialization.
void init_PORT() {
	PULSE_DDR |= (1<<DDB4);
	PULSE_PORT |= (1<<PORTB4);
}

 

측정)

PB4 (OC0)를 펄스 파형 출력핀으로 설정
Oscilloscope 를 통해 duty ratio = 24%, 주파수 = 244.153Hz인 펄스 파형을 측정