제민

[0x07] 타이머/카운터 인터럽트 (2) - Fast PWM 본문

전기전자/Atmega128

[0x07] 타이머/카운터 인터럽트 (2) - Fast PWM

jemin0619 2024. 4. 6. 21:17

CLK란 HIGH와 LOW의 주기가 같은 펄스이다.

 

PWM은 그림과 같이 펄스 폭을 변조하는 것을 말한다.

 

그러면 Atmega에서 이런 펄스를 어떻게 만들어내는지 그림으로 간단하게 알아보자.

그림만으로도 Atmega가 어떤 원리로 PWM 출력파형을 만들어내는지 이해할 수 있다.

이전에 사용했던 타이머 카운터 인터럽트에서의 CTC(비교) 모드와 마찬가지로 OCRn를 설정하면 TCNTn가 카운트를 하고, 카운트가 OCRn이 되면 무언가 동작한다. 

그림에서는 TCNTn==OCR0에 RST가 된다.

 

COMn1 COMn0

1 | 0 | OCR0 = TCNT0면 OcCn 출력값을 CLR, TCNT가 0이면 SET

1 | 1 | 같아지면 출력값을 SET, TCNT가 0이면 CLR

 

즉 1 0을 써야 한다.

분주비는 앞으로 왠만해서 8을 사용하려 한다.

 

출력핀 OCn은 OC0의 경우 PB4이다.


LED 밝기를 조절하는 코드를 살펴보자.

TCCR0 설정은 FAST PWM, OCR0==TCNT0에 RST, 8분주비 로 구성된다.

PWM 출력핀이 B에 존재하므로 Port B를 출력핀으로 설정해준다.

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

int main(void){
	DDRB = 0xff;
	TCCR0 = 0b01101010;
	while(1){
		for(int i=0;i<=255;i++){
			OCR0 = i; 
			_delay_ms(5);
		}
	}
}

 


0~5까지 밝기가 변하면서 1 Digit Fnd에 해당 밝기를 출력하는 코드를 살펴보자.

turn 변수를 사용해 밝기의 이동을 구현했다.

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

volatile int turn=0,cnt=0;
volatile int bright[6]={0,51,102,153,204,255};
volatile int pattern[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};

int main(void){
	DDRA = 0xFF;
	DDRB = 0xFF;
	TCCR0 = 0b01101010;
	while(1){
		PORTA = pattern[cnt];
		OCR0 = bright[cnt];
		_delay_ms(500);
		if(turn==0) cnt++;
		if(turn==1) cnt--;
		if(cnt>5) {cnt=4; turn=!turn;}
		if(cnt<0) {cnt=1; turn=!turn;}
	}
}

'전기전자 > Atmega128' 카테고리의 다른 글

[0x08] ADC  (0) 2024.04.06
[0x06] 타이머/카운터 인터럽트 (1) - Normal, CTC  (0) 2024.03.28
[0x05] FND  (1) 2024.03.28
[0x04] 외부 인터럽트  (1) 2024.03.28
0317 수행평가 - 1  (0) 2024.03.20