주기적 타이머

컴퓨터나 임베디드시스템에서 **주기적 타이머**는 주기적으로 반복되는 동작을 하기 위해 디지털 하드웨어 회로에 의해 신호를 만든다. 이 신호에 따라 컴퓨터의 인터럽트 처리 방식을 사용하여 주기적인 작업을 수행하는 것이 일반적 처리 방법이다.url-status=deadurl-status=dead 소프트웨어 기계어 실행없이 일정 시간을 만들 수 있기 때문에 중앙 처리 장치(CPU)의 부담을 줄일 수 있다. 클럭과 디지털회로를 사용하므로 정확한 시간을 얻을 수 있다. 컴퓨터 시스템의 필수 요소이며, 현실적으로 소프트웨어로 일정 시간을 얻는 것이 아주 간단한 시스템 아니면 기계어 코드의 복잡성 때문에 힘들어 타이머에 의존한다.url-status=dead 실시간 시계와 다르게 CPU의 클럭 신호를 주로 이용하여 디지털회로에 필요한 클럭을 만든다. 보통 CPU 클럭이 주파수가 높아 빠르기 때문에 프리 스켈일러(prescaler) 회로에 의해 주파수를 낮추어 타이머 모듈에 공급한다.url-status= dead 카운터 회로에 의해 일정 시간이 되면 인터럽트 디지털 신호를 발생하고, CPU가 접수하면 현재 실행하는 기계어 코드를 종료한 후 해당 인터럽트 처리 루틴(ISR)을 자동 호출한다. 인터럽트 발생 여부는 레지스터 설정에 의해 선택적으로 처리할 수 있다. 인터럽트를 발생하는 부분과 인터럽트를 수용하는 CPU가 처리할 것인가는 레지스터 설정에 의해 별도로 동작 시킬 수 있다. 일정 주기의 듀티를 변경하여 만드는 PWM 신호도 타이머의 카운터와 비교 회로에 의해 쉽게 만들 수 있다. 인터럽트와의 결합여부는 응용에 따라 반복적으로 같은 듀티를 사용할 수도 있고, 실행 중간에 듀티값을 변경할 수도 있다.
# 마이크로컨트롤러에서 주기적 타이머 활용 예
컴퓨터 시스템에서 마이크로컨트롤러는 하나의 칩에 여러 가지 기능을 하는 모듈이 결합되어 있고, 이중에 가장 대표적인 모듈이 주기적 타이머이다. 대부분의 마이크로컨트롤러는 타이머를 내장하고 있다. 타이머의 구성은 각 칩에 따라 성능과 기능이 다르다. 칩의 성능에 따라 제조사에서 몇개의 타이머 모듈을 넣을 지를 결정하여 다양한 모델의 마이크로컨트롤러를 만든다.
## AVR 타이머
AVR의 대표적 모델인 ATmega 시리즈는 8비트와 16비트 타이머를 사용한다. AVR8의 여러 가지 모델 중, 타이머 번호는 일반적으로 다음과 같이 배치되어 있다 : * 타이머 0, 2: 8비트 카운터 타이머 * 타이머 1, 3: 16비트 카운터 타이머 카운터 비트수가 늘어나면 긴 주기의 시간을 만들 수 있으므로 시스템 사양에 따라 적절히 선택하여 사용하면 된다.
### 프리스케일러
AVR8 프리스케일러 예 AVR8 시리즈에서 사용하는 프리스케일러의 예에서, 시스템 클럭으로 최대 1024분주까지 얻을 수 있다. CS 레지스터의 값에 따라서 분주 값을 설정하여 빠르기를 조절할 수 있다. T0, T1외부 핀에서 입력되는 클럭으로 선택적으로 사용할 수 있다.
### 타이머 0
AVR8 타이머0 구조 AVR8 타이머0 인터럽트 발생 ATmega328P등의 AVR8 시리즈의 타이머0는 8비트 카운터를 사용한다. 프리스케일러로부터 입력되어 선택된 클럭을 사용하여 일정한 주기를 얻을 수 있다. 동작모드를 다양하게 설정할 수 있고, 만약 인터럽트를 사용한다면 타이머의 설정한 최댓값까지 도달하면 TOV0가 설정되고, 인터럽트 가능 레지스터 설정에 따라 인터럽트 신호가 작동한다. AVR8의 인터럽트를 활용한 타이머0 프로그래밍 예 (avr-gcc 컴파일러를 사용할 경우) : #include #include int main(void) { TIMSK |= (1 << TOIE0); // 인터럽트 가능하게 설정 TCCR0 |= (1 << CS01) | (1 << CS00); // 프리스케일러 64분주로 설정 sei(); // CPU가 인터럽트 받아 들여 처리 시작하게 설정 while (1) { // 시스템 전체를 제어 } } // 타이머0 오버플로워 인터럽트 핸들러 ISR (TIMER0_OVF_vect) { // 주기적인 일이 필요할 때, 해당 기능을 프로그래밍 }
## 8051 타이머
처음 모델의 8051 타이머는 2개가 장착되었다. 8051이 다양한 회사에서 출시되면서, 성능도 향상과 함께 다양한 모델이 나오면서 타이머 역시 기능과 개수가 다양하다. 타이머의 동작은 다음 두가지를 선택할 수 있다.url-status=dead * 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 통합 개발 환경) :날짜확인=2015년6월19일 #include #include /*------------------------------------------------ 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) { // 메인 루프 } } 인터럽트 핸들러의 표현은 표준 C/C++가 아니므로 개발환경에 따라 다르다. : /// IAR E.W. 통합 개발 환경에서 인터럽트 핸들러의 표현 /// #pragma vector=0x0b __interrupt void timer0_interrupt_handler(void) { // ... } /// SDCC 컴파일러에서 인터럽트 핸들러의 표현 /// #include void Timer0_ISR(void) __interrupt (1) { // ... }