AVR에서 Timer 사용하기
AVR에는 두가지 타입의 타이머가 있다. 2^8=256까지 카운터가 가능한 8비트 그리고 2^16=65535까지 카운터가 가능한 16비트 타이머..
카운터가 MAX값인 255에 도달하면 오버플로우가 발생하여 다시 값은 0이되는 것을 아래 그림에서 보여주고 있다.
Arduino Uno에서 사용하는 Atmega328p 마이크로 컨트롤러에는 3개의 타이머가 있다.
timer 0와 timer 2는 8비트 타이머이고 Timer1은 16 비트 타이머이다.
Prescaler
사용중인 크리스탈의 값 F_CPU = 4Mhz라고 가정하자. 그리고 16비트 타이머(최대값 65535)를 사용한다고 가정하면 최대 만들 수 있는 delay의 값 16.384ms이다. 계산 과정은 아래와 같다.
주기 = 1/주파수 = 1/4000000Hz = 0.00000025s = 0.00025ms
타이머 카운터 = 필요한 딜레이 시간 / 클록 시간 주기 – 1
65535 = X /0.00025ms -1
X = 65536*0.00025ms=16.384ms
그럼 20ms의 딜레이 시간을 얻을려면 어떻게 해야 할까? 프리스케일러를 사용하면 F_CPU의 값을 낮출 수 있다. 다시 말하면 시간 주기값을 크게 할 수 있다.
F_CPU = 4Mhz => 1/4000000Hz = 0.00000025s = 0.00025ms
4Mhz / 8 = 4000000/8 = 500000Hz => 0.000002 s = 0.002ms
4Mhz / 64 = 4000000/64 = 62500Hz => 0.000016 s = 0.016 ms
4Mhz / 256 = 4000000/256 = 15625Hz =>0.000064 s = 0.064ms
4Mhz / 1024 = 4000000/1024 = 3906.25 Hz=>0.000256 s = 0.256ms
이제 20ms의 시간을 얻기 위해 위해서 계산한 클록 시간 주기 값들을 식에 대입해보면
타이머 카운터 = 필요한 딜레이 시간 / 클록 시간 주기 – 1
20ms/0.00025ms– 1 = 80000-1 = 79999 => 16비트 타이머의 범위인 65535를 넘어가는 값이므로 사용 불가
20ms / 0.002ms -1 = 10000 – 1 = 9999 =>8 프리스케일러를 사용함으로써 이제 16비트 타이머를 사용하여 원하는 결과를 얻을 수 있다.
20ms/0.016ms-1=1250 – 1 =1249 =>64 프리스케일러를 사용함으로써 이제 16비트 타이머를 사용하여 원하는 결과를 얻을 수 있다.
20ms/0.064ms-1=312.5-1=311.5
20ms/0.256ms -1 = 78.125-1=77.125
프리스케일러(Prescaler) 선택하기
16Mhz / 8 = 16000000/8 = 2000000Hz => 0.0000005 s = 0.0005ms
250ms/0.0005ms-1 = 500000 -1 = 499999 =>16비트 사용범위를 넘어섬
16Mhz / 64 = 16000000/64 = 250000Hz => 0.000004 s = 0.004ms
250ms/0.004ms-1 = 62500 -1 = 62499 =>16비트 카운터 사용가능
16Mhz / 256 = 16000000/256 = 62500Hz => 0.000016 s = 0.016ms
250ms/0.016ms-1 = 15625 -1 = 15624 =>16비트 카운터 사용가능
16Mhz / 1024 = 16000000/1024 = 15625Hz => 0.000064 s = 0.064
250ms/0.064ms-1 = 3906.25 -1 = 3905.25 =>소수점 있음
두 가지 모두 똑같은 결과를 얻을 수 있었다. 상태값이 250ms마다 변하므로 주기가 500ms인 파형이 그려지게 된다.