타이머는 우리가 매일 사용하는 자명종과 같은 것이다. 자명종과 스톱위치의 기능을 가지고 있다고 생각하면 된다. 앞의 3장에서 보았던 GPIO로 LED켜기에서 우리는 시간 지연 함수를 사용해 보았다. 일정한 시간을 정해 놓고 그시간이 흐른 후에 다음일을 하도록 하기 위한 것이었다. 그런데, 그 예제에서 사용한 시간지연 함수는 소프트웨어로 시간지연을 하기 때문에 정확한 시간을 잴 수는 없다. 시간 지연 함수를 설명할 때 언급했던 바와 같이, 임베디드 시스템에서 정확한 시간재기는 필수적인 요소이다. 특히 정확한 시간지연이 필요한 경우에 타이머/카운터를 사용하게 된다. 마이크로컨트롤러에서 타이머/카운터는 일정한 개수만큼의 클럭을 세어 정해진 시간이 되면 인터럽트를 발생시키는 역할을 하게 된다. 소프트웨어 시간지연 함수가 일정 시간동안 MCU에게 엉뚱한 작업을 시킴으로써 MCU의 동작을 정지시키는 반면타이머는 필요한 시간을 미리 레지스터에 설정하고, 다른 작업과 병행하게 타이머가 동작하고, 설정한 조건에서 인터럽트 발생하게 함으로써, MCU의 효율을 극대화 시킬 수 있다. 이번 장에서는 마이크로컨트롤러들의 기능들중 가장 중요한 기능의 하나인 타이머/카운터 기능을 설명한다.
디지털 회로에서 클럭은 주어진 일을 순서대로 정확한 시간에 처리하기 위해 사용된다. 클럭은 말 그대로 시계의 역할을 하며, 일정한 시간 간격으로 0과 1의 값이 번갈아 나타나게 되어 있다. 이렇게 0과 1이 번갈아 한번 나타나는 시간을 주기라고 하며, 1초당 몇번이나 0과1이 변화되었는가를 주파수라 한다. 즉, 1MHz라고 하면 초당 1,000,000번 0과 1이 반복됨을 뜻한다. 카운터는 이 클럭을 세는 장치를 말한다. 클럭이 하나 발생(즉, 0과 1의 변경)할 때마다, 카운터는 1씩 증가하게 된다. 이와 같이 클럭과 카운터에 의해서 임베디드 시스템의 시계가 만들어지는 것이다. 카운터의 크기는 그 카운터의 비트수에 따라 달라진다. 3비트 카운터를 예로 보인 것으로, 0~7까지 셀수 있다. 8비트 카운터라면 2의 8승, 즉 0~255까지를 셀 수 있다. 카운터에 의해서 시계가 만들어질 수 있는데, 만약 클럭의 주기가 1ms라면 8비트 카운터가 0~255까지 한번 세는데 256ms가 필요하고, 이것이 4번 반복되면 1초가 되는 것이다. 만약 클럭의 주기가 4ms라면 8비트 카운터로 0~255까지 한번만 세면 1초가 된다. 이와 같이, 클럭과 카운터를 이용하여 마이크로컨트롤러의 타이머/카운터가 만들어진다. 따라서, 타이머는 사용하는 클럭의 주기와 카운터 크기에 따라 그 특성이 결정된다. 우리가 만약 일정한 크기의 타이머를 만들기 원한다면, 먼저 숫자를 세기 위해 사용할 클럭이 있어야 할 것이며, 그 클럭을 이용하여 숫자를 셀 카운터가 있어야 한다. 또한, 원하는 시간을 얻기 위해 그 카운터를 시작시킬 조건과 끝낼 조건이 필요하다. 그리고, 원하는 숫자가 세어졌을 때 이를 MCU에 알릴 인터럽트 기능이 필요하다. 이와 같은 기능들이 대부분의 마이크로컨트롤러에 내장되어 있으며, AT89C51ED2 에도 역시 클럭들과 여러 레지스터들, 카운터, 그리고 이를 제어할 제어 로직을 가지고 있다.
AT89C51ED2의 타이머/카운터도 위와 같은 원리에 의해 만들어진다. 통상 타이머는 MCU 내부 클럭을 세는 장치를 일컬으며, 카운터는 MCU의 외부에서 입력되는 클럭을 세는 장치를 일컫는다. 이 절에서는 AT89C51ED2의 타이머/카운터 기능에 대해서 살펴보도록 하자. AT89C51ED2는 타이머 0~2의 3개의 타이머/카운터와 5개의 PCA를 보유하고 있다. 이들은 인터럽트와 PWM 출력 기능을 갖고 있다. 인터럽트 기능은 타이머가 가지고 있는 시계 기능에 자명종 기능을 추가해 주기 위한 것으로, 다양한 방법으로 인터럽트를 발생시켜 프로그램이 수행될 때, 자동적으로 시간을 알려주는 역할을 한다.
AT89C51ED2가 보유한 타이머 0, 1 타이머/카운터는 정확한 시간을 구하기 위한 타이머 오버플로우 또는, UART 통신의 클럭으로 사용된다. 타이머0,1 의 타이머/카운터에 사용되는 입력 클럭은 크게 2가지로 나누어 진다. 첫째로, MCU내부에 있는 내부 발진 클럭을 12분주한 클럭을 사용하는 방식과 둘째로, MCU외부단자 T0,T1에 입력되는 외부 펄스를 계수하는 방식이 있다 이때, 첫번째 방식을 사용하는 경우는 타이머라고 하고 2번째의 경우는 카운터라고 한다. 타이머/카운터0,1은 8비트은 TH0,TL0(TH1,TL1)라는 특수기능레지스터를 사용하는데, 타이머/카운터0,1 클락이 발생될때마다 이 레지스터에 1씩 증감되는데, 최대값까지 다 더해져서,(예:TH0와 TL0가 0xFF인 경우) 0 이 되면, 오버플로우 인터럽트가 발생된다. 타이머/카운터0,1은 TMOD 라는 레지스터를 어떻게 설정하느냐에 따라 모드0에서 모드3까지 전부 4개의 모드를 사용 할 수있다.
타이머 2는 타이머0,1과는 달리, Input Capture를 가지고 있으며, autoreload 기능 및 시리얼 통신 클럭 발생기능을 가지고 있다. 그리고 카운터값을 저장하는 TH2, TL2가 1씩 더해져서 0xFF에서 0 이 되는 오버플로우 말고도 카운팅을 반대로 해서 다운플로우도 설정할 수 있다.
1) TMOD(Timer Mode) : 타이머/카운터0,1의 운영 및 동작모드에 대한 레지스터이다. 하위 4비트(0~3)은 타이머/카운터 0 를 위한 레지스터고, 상위 4비트(4~7)은 타이머/카운터 1을 위한 레지스터이다. 비트 7, 3은 GATE(타이머/카운터를 제어하는 비트)이다. GATE가 0이면 외부핀의 제어를 받지않는다. GATE가 1이면 외부에서 카운터를 제어한다. 외부핀 INT0에 High(1)값이 들어오면 카운터가 시작하고, 외부핀 INT0에 Low(0)값이 들어오면 카운터는 정지한다. (타이머/카운터1은 INT1) 비트 6,2는 C/T (Conter/timer selector)이다. 타이머/카운터의 입력클럭을 결정하는 비트이다. 이 비트가 1이면 메인클럭/12의 클럭를 사용하며(내부클럭) 이 비트가 0이면, 외부핀 T0,T1의 입력되는 클럭을 사용한다.(외부클럭사용) M1,M0는 동작모드를 결정하는 비트이다.
2) TCON(Timer/Counter 0 and 1 Control) : 타이머/카운터0,1 제어 레지스터이다. 상위 4비트(4-7)가 타이머/카운터0,1 제어용이며, 나머지 하위비트는 외부인터럽트용 비트이다. 비트 7은 TF1(Timer overflow flag1) 타이머 카운터1이 오버플로우 되었을 때, 자동으로 1로 설정된다. 인터럽트를 사용하는 경우, 인터럽트 서브루틴이 실행되면, 자동적으로 0이 된다. 비트 6은 TR1(timer run control 1) 타이머 카운터 1의 동작 제어 비트이며, 이 비트가 1이면 카운트를 시작하고, 0이면 카운트를 정지한다. 비트 5는 TF0(Timer overflow flag 0) 타이머/카운터0 오버플러우 플래그, 기능은 TF1과 같다. 비트 4는 TR0(Timer run control 0) 타이머 카운터 0의 동작 제어 비트, 그 기능은 TR1과 같다.
3) THn/TLn(Timer/Counter n High/Low Byte) : 타이머/카운터 레지스터이다. 타이머/카운터 n의 8비트 카운터 값을 저장하고 있는 레지스터를 뜻한다.
1) T2MOD(Timer 2 Mode Control Register) : 타이머/카운터2 모드 제어 레지스터이다. 비트 1은 T2OE(Timer 2 Output Enable bit) 이 비트를 0으로 설정하면, P1.0/T2를 클럭입력 또는 GPIO로 사용되며, 1로 설정하면, P1.0/T2는 클럭출력으로 사용된다. 비트 0은 DCEN (Down Counter Enable bit) 이 비트를 0으로 설정하면, up/down 카운터를 disable로 설정하며, 1로 설정하면, enable로 설정한다.
2) T2CON(Timer 2 Control Register) : 타이머/카운터2 제어 레지스터이다. 비트 7은 TF2(Timer 2 overflow Flag), 비트 6은 EXF2 (Timer 2 External Flag) EXEN2 = 1 일때, T2EX핀으로부터 입력을 받아, reload/capture가 발생될 때, 타이머2 인터럽트 서비스 루틴이 실행때될 때, 이 비트는 1로 설정된다. up/down카운터를 사용하지 않느다면, DCEN = 1이면 소프트웨어적으로 이 비트를 0으로 설정해야 한다. 비트 5는 RCLK (Receive Clock bit) 타이머1오버플로우를 모드1 또는 3 에의한 시리얼포트 수신클럭으로 사용될 때, 이 비트는 0이된다. 타이머2 오버플로우인경우는 1이 된다. 비트 4는 TCLK(Transmit Clock bit) 송신클럭에 대해서만 제외하고, RCLK비트와 내용은 같다. 비트 3은 EXEN2(Timer 2 External Enable bit) 이 비트가 0 이면 T2EX핀에 대한 입력을 무시한다. 타이머2가 시리얼포트 클럭으로 사용되지 않을 때, T2EX핀의 입력을 받아 capture/reload가 발생되면 이 비트는 1이 된다. 비트 2는 TR2 (Timer 2 Run control bit). 비트 1는 C/T2# (Timer/Counter 2 select bit) 내부 시스템클럭을 타이머2 동작클럭으로 사용하기 위해서는 이 비트를 0으로 설정하고, T2핀의 입력을 사용하기 위해서는 1로 설정한다. 비트 0은 CP/RL2# (Timer 2 Capture/Reload bit) RCLK와 TCLK이 1이면, 이 비트는 무시되고, 타이머2는 autoreload로 동작한다. 타이머2 오버플로우가 autoreload 될때, 이 비트는 0으로 설정되며, EXEN비트가 1이고, T2EX핀으로 capture되면 1로 설정된다.
3) RCAP2H /RCAP2L (Timer/Counter 2 Reload/Capture High/Low Byte) 타이머2가 aute-reload모드로 동작할 때, TH2,THL 레지스터가 자동으로 이 값들을 참조하여 다시 설정하게 된다. 타이머0,1과는 달리 타어머2 auto-reload는 16비트 카운터이기 때문이다.
댓글 영역