반응형

사실 저번 외부인터럽트 한개 써놓고 소자 도착하면 그냥 하던거나 해야지!! 했는데 저번 글 호응이 이상하리만큼 높았습니다(......)

 

 

정말 저도 잘 못하는데!! 안쓸수도 없고...ㅇ<-<

 

 

이번엔 타이머/카운터 설명을 하겓습니다. 아씨 진짜 잘모르는데 ㅋㅋㅋㅋㅋㅋ

 

 

먼저! 타이머/카운터가 뭐냐하면,

기본적으로 ATmega128을 비롯한 MCU들이 시간을 세기 위해서 쓰는게 크리스탈입니다.

 

 

 

저놈인데요, 쟤가 16MHz의 펄스를 계속 내보내고, 그 펄스를 이용해서 MCU가 자체적으로 시간을 셉니다.

 

 

 

요런식의 펄스를 세는게 타이머/카운터이고,

 

MCU 내부 시스템 클럭을 세는게 타이머, 외부 핀에서 들어오는 펄스를 세는게 카운터입니다.(TOSC1,2, T1,2,3)

 

 

카운터는 패스하고, 타이머에 대해서 좀 알아보죠.

 

 

먼저, 프리스케일러라는게 있습니다. 분주비라고도 하는데요, 아까 얘기드렸던 것 같이 시스템 클럭은 16MHz, 한 펄스가 1/16us짜리입니다.

 

요걸로 1초마다 동작하는 타이머를 쓰려고 한다면.. 좀 많이 세어야겠죠? 그래서 분주비라는걸 씁니다.

예를 들어 16MHz를 2분주 시킨다면 8MHz, 1/8us가 되겠네요.

ATmega128은 총 네가지 타이머를 지원합니다. timer/counter 0,1,2,3 네가지로요.

이 중에서, timer/counter0,2 는 8비트 타이머, timer/counter1,3은 16비트 타이머입니다.

 

차이점이라면 8비트 카운터는 0x00~0xFF까지 세는거고요, 16비트 카운터는 0x0000~0xFFFF까지 셀 수 있습니다.

 

일단 8비트 타이머에 대해 설명하도록 할게요.

 

 

타이머의 동작 모드는 총 네개가 있습니다.

Normal 모드, CTC 모드, Fast PWM 모드, Phase Correct PWM 모드가 있는데요, 뒤에 두개는 PWM동작입니다. 다음에 설명하도록 하고 ^^;

 

 

Normal 모드와 CTC 모드는 인터럽트가 다릅니다.

 

 

Normal 모드는 timer/counterX overflow interrupt이고, CTC 모드는 timer/counterX compare match interrupt 입니다.

 

 

 

 

 

 

 

 

 

 

요게 Normal 모드입니다.

현재값은 TCNTn 레지스터에 저장되고, 말 그대로 TCNTn이 0xFF가 되면 오버플로우가 일어납니다.

 


 

 

이게 CTC모드인데요, TCNTn이 증가하는건 노멀모드와 동일하지만, 여기서는 OCRn이라는 레지스터를 하나 더 설정해줍니다.

TCNTn == OCRn이 되면 TCNTn은 다음 비트에서 0으로 클리어, 출력 비교 인터럽트가 일어나게 됩니다. 물론 OCRn을 0xFF로 설정할 수는 있습니다만.. 그럼 오버플로우랑 똑같죠뭐 ㅡ,.ㅡ

 

 

그럼 실제로 사용하기 위한 타이머 0의 레지스터들을 알아보죠. 사실 위에꺼 잘 몰라도 레지스터만 알면 써먹어 집니다(....)

 

 

1. TCNT0

..그림에서도 보셨겠지만 냅두면 알아서 0x00~0xFF까지 왔다갔다합니다.

 

 

2. OCR0

TCNT0와 계속 비교되는 값입니다. 같아지면 출력 비교 인터럽트가 일어납니다.

3. TIMSK

 

 

 

타이머/카운터0는 마지막 두 비트를 쓰는데, 비트 0이 타이머/카운터0 노멀모드, 비트 1이 타이머/카운터0 CTC모드 셋입니다.

TIMSK = 0b00000001이면 노멀모드 인에이블, TIMSK = 0b00000010이면 CTC모드 인에이블이겠죠.

 

 

4. TCCR0

 

 

쬐끔 복잡합니다.

 

 

6번비트와 3번비트는

 

 

00일때 노멀, 01일때 CTC, 10일때 phase correct PWM, 11일때 fast PWM입니다.

 

 

2번에서 0번비트는 위에 잠깐 언급했던 분주비 설정입니다.

 

000일때 타이머/카운터 동작 중지

001일때 1분주(분주비 사용 X)

010일때 8분주

011일때 32분주

100일때 64분주

101일때 128분주

110일때 256분주

111일때 1024분주가 됩니다.

 

 

 

 

뭔가 설명은 길었는데, 실제로 쓰실때는 레지스터 세개정도? 에 저번에 했던 SREG레지스터 설정해서 쓰시면 됩니다.

예시 하나 보실까요?

 

 

 

 

 

 

타이머/카운터0을 이용해 LED를 0.5초마다 켰다껐다하는 동작입니다.

 

 

 

타이머0을 위해 들어간 코드는

9~13번줄입니다.

 

 

 

 

 

 

  1. TIMSK = 0b00000001; // TOIE0 = 1;
  2. TCCR0 = 0b00000111; // 일반모드, 프리스케일 = CK/1024
  3. TCNT0 = 0b00000000; // 타이머/카운터0 레지스터 초기값
  4. SREG = 0b10000000; // 전역 인터럽트 인에이블 비트 I 셋

 

TIMSK = 0b00000001; 타이머/카운터0 노멀모드 인에이블이고,

TCCR0의 6번, 3번비트는 0 : 노멀모드, 2~0번비트 111 : 1024분주비 사용입니다.

TCNT0값이 설정 가능하기는 한데, 여기서는 초기값이네요.

 

 

그리고 SREG = 0x80으로 인터럽트 사용 설정을 해줍니다.

 

요건 인터럽트 함수인데요,

 

  1. // 1/16us x 1024 x 256 = 16.384ms
  2. interrupt [TIM0_OVF] void timer_int0(void)
  3. {
  4. cnt++;
  5. if(cnt == 31) { // 16.384ms x 31 = 0.5sec
  6. led = led ^ 0xFF;
  7. PORTB = led;
  8. cnt = 0;
  9. }
  10. }

 

노멀모드의 경우

interrupt[TIMn_OVF] void timer_intn(void)

{

}

 

로 사용하고,

 

CTC모드의 경우

interrupt[TIMn_COMPA] void timer_compna(void)

{

}

로 씁니다.

 

 

 

한번 인터럽트 걸리는게 16.384ms이고, 그걸 31번 반복해서 0.5sec를 맞추는겁니다. 자기가 쓰고자 하는 시간에 맞춰서 분주비나 기타등등을 맞춰서 해 주시면 되는데...

 

 

귀찮으신분들을 위해 밑에 비기(!)를 몇개 소개해봅니다. 네이년 검색하다 찾았네요

 

 

 

 

 

//=====================================================

 

// 타이머0 오버플로우 인터럽트
TCCR0=3; TCNT0=156; TIMSK=1; //16000000/ 32/100=5000Hz=200us,(256-100)=156
TCCR0=4; TCNT0=6; TIMSK=1; //16000000/ 64/250=1000Hz=1ms, (256-250)=6
TCCR0=5; TCNT0=131; TIMSK=1; //16000000/ 128/125=1000Hz=1ms, (256-125)=131
TCCR0=5; TCNT0=6; TIMSK=1; //16000000/ 128/250= 500Hz=2ms, (256-250)=6
TCCR0=6; TCNT0=6; TIMSK=1; //16000000/ 256/250= 250Hz=4ms, (256-250)=6
TCCR0=7; TCNT0=100; TIMSK=1; //16000000/1024/156=100.16Hz=0.984ms, (256-156)=100
TCCR0=7; TCNT0=6; TIMSK=1; //16000000/1024/250=62.5Hz=16ms, (256-250)=6

// 타이머0 매치 인터럽트
TCCR0=0x0B; OCR0= 28; TIMSK=2; //16000000/ 32/(1+ 28)=17241.37931Hz=58us
TCCR0=0x0B; OCR0= 49; TIMSK=2; //16000000/ 32/(1+ 49)=10000Hz=100us
TCCR0=0x0B; OCR0= 99; TIMSK=2; //16000000/ 32/(1+ 99)= 5000Hz=200us
TCCR0=0x0C; OCR0= 74; TIMSK=2; //16000000/ 64/(1+ 74)= 3333.3Hz=300us
TCCR0=0x0C; OCR0=124; TIMSK=2; //16000000/ 64/(1+124)= 2000Hz=500us
TCCR0=0x0C; OCR0=249; TIMSK=2; //16000000/ 64/(1+249)= 1000Hz=1ms
TCCR0=0x0D; OCR0=124; TIMSK=2; //16000000/ 128/(1+124)= 1000Hz=1ms
TCCR0=0x0D; OCR0=249; TIMSK=2; //16000000/ 128/(1+249)= 500Hz=2ms
TCCR0=0x0E; OCR0=249; TIMSK=2; //16000000/ 256/(1+249)= 250Hz=4ms
TCCR0=0x0F; OCR0= 71; TIMSK=2; //14745600/1024/(1+ 71)= 200Hz=5ms
TCCR0=0x0F; OCR0=155; TIMSK=2; //16000000/1024/(1+155)= 100.16..Hz=9.984ms
TCCR0=0x0F; OCR0=249; TIMSK=2; //16000000/1024/(1+249)= 62.5Hz=16ms

// 타이머1 오버플로우 인터럽트
TCCR1B=1; TCNT1=49536; TIMSK=4; //16000000/ 1/16000=1000Hz=1ms, (65536-16000)=49536
TCCR1B=1; TCNT1=33536; TIMSK=4; //16000000/ 1/32000= 500Hz=2ms, (65536-32000)=33536
TCCR1B=2; TCNT1=63536; TIMSK=4; //16000000/ 8/ 2000=1000Hz=1ms, (65536- 2000)=63536
TCCR1B=2; TCNT1=61536; TIMSK=4; //16000000/ 8/ 4000= 500Hz=2ms, (65536- 4000)=61536
TCCR1B=2; TCNT1=45536; TIMSK=4; //16000000/ 8/10000= 200Hz=5ms, (65536-10000)=45536
TCCR1B=2; TCNT1=35536; TIMSK=4; //16000000/ 8/20000= 100Hz=10ms, (65536-20000)=35536
TCCR1B=3; TCNT1=65286; TIMSK=4; //16000000/ 64/ 250=1000Hz=1ms, (65536- 250)=65286
TCCR1B=4; TCNT1=59286; TIMSK=4; //16000000/256/ 6250= 10Hz=100ms,(65536- 6250)=59286
TCCR1B=4; TCNT1=34286; TIMSK=4; //16000000/256/31250= 2Hz=500ms,(65536-31250)=34286
TCCR1B=4; TCNT1= 3036; TIMSK=4; //16000000/256/62500= 1Hz=1sec, (65536-62500)= 3036

// 타이머1 A매치 인터럽트
TCCR1B=0x09; OCR1A= 1474; TIMSK=0x10; //14745600/ 1/(1+ 1474)=9997.01695Hz=100.02984us
TCCR1B=0x09; OCR1A= 1599; TIMSK=0x10; //16000000/ 1/(1+ 1599)=10KHz=100us
TCCR1B=0x09; OCR1A= 3999; TIMSK=0x10; //16000000/ 1/(1+ 3999)= 4KHz=250us
TCCR1B=0x09; OCR1A=15999; TIMSK=0x10; //16000000/ 1/(1+15999)=1000Hz=1ms
TCCR1B=0x09; OCR1A=31999; TIMSK=0x10; //16000000/ 1/(1+31999)= 500Hz=2ms
TCCR1B=0x0A; OCR1A= 1999; TIMSK=0x10; //16000000/ 8/(1+ 1999)=1000Hz=1ms
TCCR1B=0x0A; OCR1A= 3999; TIMSK=0x10; //16000000/ 8/(1+ 3999)= 500Hz=2ms
TCCR1B=0x0A; OCR1A= 4999; TIMSK=0x10; //16000000/ 8/(1+ 4999)= 400Hz=2.5ms
TCCR1B=0x0A; OCR1A= 9999; TIMSK=0x10; //16000000/ 8/(1+ 9999)= 200Hz=5ms
TCCR1B=0x0A; OCR1A=19999; TIMSK=0x10; //16000000/ 8/(1+19999)= 100Hz=10ms
TCCR1B=0x0A; OCR1A=18431; TIMSK=0x10; //14745600/ 8/(1+18431)= 100Hz=10ms
TCCR1B=0x0A; OCR1A=39999; TIMSK=0x10; //16000000/ 8/(1+39999)= 50Hz=20ms
TCCR1B=0x0A; OCR1A=59999; TIMSK=0x10; //16000000/ 8/(1+59999)= 33.33Hz=30ms
TCCR1B=0x0B; OCR1A= 249; TIMSK=0x10; //16000000/ 64/(1+ 249)=1000Hz=1ms
TCCR1B=0x0C; OCR1A= 3124; TIMSK=0x10; //16000000/256/(1+ 3124)= 20Hz=50ms
TCCR1B=0x0C; OCR1A= 6249; TIMSK=0x10; //16000000/256/(1+ 6249)= 10Hz=100ms
TCCR1B=0x0C; OCR1A=12499; TIMSK=0x10; //16000000/256/(1+12499)= 5Hz=200ms
TCCR1B=0x0C; OCR1A=31249; TIMSK=0x10; //16000000/256/(1+31249)= 2Hz=500ms
TCCR1B=0x0C; OCR1A=62499; TIMSK=0x10; //16000000/256/(1+62499)=1Hz=1sec
TCCR1B=0x0D; OCR1A=62499; TIMSK=0x10; //16000000/1024/(1+62499)=0.25Hz=4sec

// 타이머3 A매치 인터럽트
TCCR3B=0x09; OCR3AH= 1474>>8; OCR3AL= 1474&0xFF; ETIMSK=0x10; //14745600/ 1/(1+ 1474)=9997.01695Hz=100.02984us
TCCR3B=0x09; OCR3AH= 1599>>8; OCR3AL= 1599&0xFF; ETIMSK=0x10; //16000000/ 1/(1+ 1999)=10KHz=100us
TCCR3B=0x09; OCR3AH=15999>>8; OCR3AL=15999&0xFF; ETIMSK=0x10; //16000000/ 1/(1+15999)=1000Hz=1ms
TCCR3B=0x09; OCR3AH=31999>>8; OCR3AL=31999&0xFF; ETIMSK=0x10; //16000000/ 1/(1+31999)= 500Hz=2ms
TCCR3B=0x0A; OCR3AH= 1999>>8; OCR3AL= 1999&0xFF; ETIMSK=0x10; //16000000/ 8/(1+ 1999)=1000Hz=1ms
TCCR3B=0x0A; OCR3AH= 3999>>8; OCR3AL= 3999&0xFF; ETIMSK=0x10; //16000000/ 8/(1+ 3999)= 500Hz=2ms
TCCR3B=0x0A; OCR3AH= 9999>>8; OCR3AL= 9999&0xFF; ETIMSK=0x10; //16000000/ 8/(1+ 9999)= 200Hz=5ms
TCCR3B=0x0A; OCR3AH=19999>>8; OCR3AL=19999&0xFF; ETIMSK=0x10; //16000000/ 8/(1+19999)= 100Hz=10ms
TCCR3B=0x0C; OCR3AH= 6249>>8; OCR3AL= 6249&0xFF; ETIMSK=0x10; //16000000/256/(1+ 6249)= 10Hz=100ms
TCCR3B=0x0C; OCR3AH=31249>>8; OCR3AL=31249&0xFF; ETIMSK=0x10; //16000000/256/(1+31249)= 2Hz=500ms
TCCR3B=0x0C; OCR3AH=62499>>8; OCR3AL=62499&0xFF; ETIMSK=0x10; //16000000/256/(1+62499)=1Hz=1sec
TCCR3B=0x0C; OCR3AH=28799>>8; OCR3AL=28799&0xFF; ETIMSK=0x10; //14745600/1024/(1+28799)=0.5Hz=2sec

// 타이머2 매치 인터럽트
TCCR2=0x0B; OCR2= 24; TIMSK=0x80; //16000000/64/(1+ 24)=10000Hz=100us
TCCR2=0x0B; OCR2=249; TIMSK=0x80; //16000000/64/(1+249)=1000Hz=1ms

//=====================================================

 

http://cafe.naver.com/circuitsmanual/116901 에 보시면 계산기도 있더라구요? 허허

반응형

+ Recent posts