{{위키데이터 속성 추적}}
<!-- {{번역 확장 필요|en|Programmable interval timer}} --->
[[컴퓨터]]나 [[임베디드]]시스템에서 '''주기적 타이머'''는 주기적으로 반복되는 동작을 하기 위해 [[디지털]] 하드웨어 회로에 의해 신호를 만든다. 이 신호에 따라 컴퓨터의 [[인터럽트]] 처리 방식을 사용하여 주기적인 작업을 수행하는 것이 일반적 처리 방법이다.<ref name="AVR8">{{웹 인용 |url=http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf |제목=ATmega Timer0,1,2,3 |확인날짜=2015-06-18 |보존url=https://web.archive.org/web/20150724032006/http://www.atmel.com/images/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf |보존날짜=2015-07-24 |url-status=dead }}</ref><ref name="Intel8051">{{웹 인용 |url=http://web.mit.edu/6.115/www/document/8051.pdf |제목=8051 Timer |확인날짜=2015-06-18 |보존url=https://web.archive.org/web/20150618100515/http://web.mit.edu/6.115/www/document/8051.pdf |보존날짜=2015-06-18 |url-status=dead }}</ref>

소프트웨어 [[기계어]] 실행없이 일정 시간을 만들 수 있기 때문에 [[중앙 처리 장치]](CPU)의 부담을 줄일 수 있다. [[클럭]]과 [[디지털]]회로를 사용하므로 정확한 시간을 얻을 수 있다. 컴퓨터 시스템의 필수 요소이며, 현실적으로 소프트웨어로 일정 시간을 얻는 것이 아주 간단한 시스템 아니면 기계어 코드의 복잡성 때문에 힘들어 타이머에 의존한다.<ref name="LimitSwTimer">{{웹 인용|url=http://betterembsw.blogspot.in/2012/12/software-timing-loops.html|제목=Software Timing Loops|확인날짜=2015년6월18일|보존url=https://web.archive.org/web/20150618173108/http://betterembsw.blogspot.in/2012/12/software-timing-loops.html|보존날짜=2015-06-18|url-status=dead}}</ref>

[[실시간 시계]]와 다르게 CPU의 클럭 신호를 주로 이용하여 디지털회로에 필요한 클럭을 만든다. 보통 CPU 클럭이 주파수가 높아 빠르기 때문에 프리 스켈일러(prescaler) 회로에 의해 주파수를 낮추어 타이머 모듈에 공급한다.<ref name="timer_basic">{{웹 인용|url= http://www.scriptoriumdesigns.com/embedded/timers.php|제목= Introduction to Embedded Programming Timer|확인날짜= 2015년6월18일|보존url= https://web.archive.org/web/20150508115557/http://www.scriptoriumdesigns.com/embedded/timers.php|보존날짜= 2015-05-08|url-status= dead}}</ref> 카운터 회로에 의해 일정 시간이 되면 [[인터럽트]] 디지털 신호를 발생하고, CPU가 접수하면 현재 실행하는 기계어 코드를 종료한 후 해당 [[인터럽트 핸들러|인터럽트 처리 루틴]](ISR)을 자동 호출한다. 인터럽트 발생 여부는 [[레지스터]] 설정에 의해 선택적으로 처리할 수 있다.  인터럽트를 발생하는 부분과 인터럽트를 수용하는 CPU가 처리할 것인가는 레지스터 설정에 의해 별도로 동작 시킬 수 있다.<ref name="AVR8" /><ref name="Intel8051" /><ref name="timer_basic" />

일정 주기의 듀티를 변경하여 만드는 [[PWM]] 신호도 타이머의 카운터와 비교 회로에 의해 쉽게 만들 수 있다. 인터럽트와의 결합여부는 응용에 따라 반복적으로 같은 듀티를 사용할 수도 있고, 실행 중간에 듀티값을 변경할 수도 있다.<ref name="AVR8" />

== 마이크로컨트롤러에서 주기적 타이머 활용 예==

컴퓨터 시스템에서 마이크로컨트롤러는 하나의 칩에 여러 가지 기능을 하는 모듈이 결합되어 있고, 이중에 가장 대표적인 모듈이 주기적 타이머이다. 대부분의 마이크로컨트롤러는 타이머를 내장하고 있다. 타이머의 구성은 각 칩에 따라 성능과 기능이 다르다. 칩의 성능에 따라 제조사에서 몇개의 타이머 모듈을 넣을 지를 결정하여 다양한 모델의 마이크로컨트롤러를 만든다.

=== AVR 타이머 ===

AVR의 대표적 모델인 ATmega 시리즈는 8비트와 16비트 타이머를 사용한다.<ref name="AVR8" />

AVR8의 여러 가지 모델 중, 타이머 번호는 일반적으로 다음과 같이 배치되어 있다 :
* 타이머 0, 2: 8비트 카운터 타이머
* 타이머 1, 3: 16비트 카운터 타이머

카운터 비트수가 늘어나면 긴 주기의 시간을 만들 수 있으므로 시스템 사양에 따라 적절히 선택하여 사용하면 된다.

==== 프리스케일러 ====
[[파일:AVR8 Prescaler.jpg|섬네일|centre|400px|AVR8 프리스케일러 예]]

AVR8 시리즈에서 사용하는 프리스케일러의 예에서, 시스템 클럭으로 최대 1024분주까지 얻을 수 있다. CS 레지스터의 값에 따라서 분주 값을 설정하여 빠르기를 조절할 수 있다. T0, T1외부 핀에서 입력되는 클럭으로 선택적으로 사용할 수 있다.

==== 타이머 0 ====

[[파일:AVR_Timer0.png|섬네일|left|400px|AVR8 타이머0 구조]]
[[파일:AVR_Timer0_int.png|섬네일|centre|400px|AVR8 타이머0 인터럽트 발생]]
ATmega328P등의 AVR8 시리즈의 타이머0는 8비트 카운터를 사용한다. 프리스케일러로부터 입력되어 선택된 클럭을 사용하여 일정한 주기를 얻을 수 있다.
동작모드를 다양하게 설정할 수 있고, 만약 인터럽트를 사용한다면 타이머의 설정한 최댓값까지 도달하면 TOV0가 설정되고, 인터럽트 가능 레지스터 설정에 따라 인터럽트 신호가 작동한다.

AVR8의 [[인터럽트]]를 활용한 타이머0 프로그래밍 예 (avr-gcc [[컴파일러]]를 사용할 경우) :
<syntaxhighlight lang="cpp">
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
        TIMSK |= (1 << TOIE0);     // 인터럽트 가능하게 설정
        TCCR0 |= (1 << CS01) | (1 << CS00);  // 프리스케일러  64분주로 설정

        sei();   // CPU가 인터럽트 받아 들여 처리 시작하게 설정

        while (1)
        {
            // 시스템 전체를 제어
        }
}

// 타이머0 오버플로워 인터럽트 핸들러
ISR (TIMER0_OVF_vect)
{
       // 주기적인 일이 필요할 때, 해당 기능을 프로그래밍
}
</syntaxhighlight>

=== 8051 타이머 ===

처음 모델의 8051 타이머는 2개가 장착되었다. 8051이 다양한 회사에서 출시되면서, 성능도 향상과 함께  다양한 모델이 나오면서 타이머 역시 기능과 개수가 다양하다.

타이머의 동작은 다음 두가지를 선택할 수 있다.<ref name="8051 타이머">{{웹 인용 |url=http://www.mikroe.com/chapters/view/65/chapter-2-8051-microcontroller-architecture |제목=Architecture and programming of 8051 MCU's, 2.6 Counters and Timers |확인날짜=2015년 8월 12일 |보존url=https://web.archive.org/web/20150814042908/http://www.mikroe.com/chapters/view/65/chapter-2-8051-microcontroller-architecture/ |보존날짜=2015년 8월 14일 |url-status=dead }}</ref>

* CPU의 동작 클럭을 이용하여 일정한 주기의 신호를 얻기
:타이머의 클럭은 보통 CPU의 메인 [[클럭 신호]]로부터 만들어진다. 이 클럭을 기반으로 우선 프리스케일러를 통해 주파수를 낮춘다. 8051은 간단히 1/12을 사용한다. 즉, 12분주 회로를 사용하여 클럭의 속도를 낮추어 타이머 모듈의 디지털 카운터 회로에 클럭을 공급한다.
* 외부의 어떤 클럭 신호가 몇개의 펄스로 동작했는지를 카운터
:외부의 클럭 신호를 타이머의 카운터 회로에 클럭으로 넣어 카운터 횟수를 파악할 수 있다. 즉, 어떤 클럭의 신호가 몇번 펄스가 발생했는지를 카운터하여 그 값을 프로그램으로 읽을 수 있다.

모드 설정에서 일정한 주기를 얻을 것인지 외부의 클럭신호의 카운터를 할 것인지는 레지스터 설정을 통해 일어어 진다.

====8051 동작모드====

* 모드 0: TH0[7:0]와 TL[4:0] 연결로 13비트 카운터로 0~8191까지 카운터 한다.
* 모드 1: TH0[7:0]와 TL[7:0] 연결로 16비트 카운터로 0~65535까지 카운터 한다.
* 모드 2: TL0[7:0] 8비트 카운터가 완료되면 TH[7:0] 레지스터 값이 TL0에 재 설정되어 카운터가 계속된다.
* 모드 3: TH0[7:0]와 TH[7:0]가 분리되어 8비트 카운터로 동작한다.

타이머 0을 사용한 프로그래밍 (Keil 통합 개발 환경) :<ref>{{웹 인용|url=http://www.keil.com/download/docs/96.asp|제목=8051 타이머 0, 모드 1 예|날짜확인=2015년6월19일}}</ref>

<syntaxhighlight lang="cpp">
#include <reg52.h>
#include <stdio.h>

/*------------------------------------------------
   Timer 0 인터럽트 핸들러
   - 65536 클럭 주기
------------------------------------------------*/
static unsigned long overflow_count = 0; // 디버깅 용으로 사용

void timer0_ISR (void) interrupt 1
{
    overflow_count++;   // 카운터 값 증가
}

void main (void)
{
     // 타이머 0 설정 :
     //   16비트 카운터 타이머 모드 설정
     //    65535 카운터 후, 오버플로워가 발생하여 인터럽트 신호가 발생한다.
     TMOD = (TMOD & 0xF0) | 0x01;  //  T/C0 모드 설정
     ET0 = 1;                      //  타이머 0 인터럽트 가능 설정
     TR0 = 1;                      //  타이머 0 동작 시작
     EA = 1;                       // 8051 코어의 인터럽트 수용하여 동작  설정 -  Global Interrupt Enable

     while (1)
     {
           // 메인 루프
     }
}
</syntaxhighlight>

인터럽트 핸들러의 표현은 표준 C/C++가 아니므로 개발환경에 따라 다르다. :
<syntaxhighlight lang="cpp">
/// IAR E.W. 통합 개발 환경에서 인터럽트 핸들러의 표현 ///
#pragma vector=0x0b
__interrupt void timer0_interrupt_handler(void)
{
    // ...
}

/// SDCC 컴파일러에서 인터럽트 핸들러의 표현  ///
#include <mcs51reg.h>

void Timer0_ISR(void) __interrupt (1)
{
   // ...
}
</syntaxhighlight>

== 같이 보기 ==
* [[인터럽트]]
* [[마이크로프로세서]]
* [[마이크로컨트롤러]]
* [[아두이노]]

== 각주 ==
<references />

[[분류:마이크로컨트롤러]]
[[분류:임베디드 시스템| ]]
[[분류:컴퓨터 시스템]]
[[분류:마이크로프로세서]]
[[분류:전자공학]]