본 글은 MSP430G2553 MCU를 기준으로 작성되었습니다.
세부적인 내용은 제품군마다 조금씩 다를 수 있습니다.
MCU에서 말하는 타이머에는 두 가지 기능이 있다.
타이머 기능은 사용자가 설정한 시간이 경과되면 이를 MCU로 알려주는 기능이다. 한 번만 알려주도록 할 수도 있으며, 반복적으로 알려주도록 할 수도 있다.
스톱워치 기능은 사용자가 임의의 이벤트의 경과 시간을 측정할 수 있도록 도와주는 기능이다. 사용자가 타이머 내부에 있는 카운터를 시작/정지할 수 있도록 제공하여 원하는 시간을 측정할 수 있다.
MSP430에는 Timer A와 Timer B 모듈이 있다. Timer B는 Timer A의 확장형으로써 캡처/비교 레지스터 수가 Timer A보다 많은 등의 특징이 있다. MSP430G2553에는 두 개의 Timer A를 제공하며, Timer B는 제공하지 않는다.
Timer A의 특징은 아래와 같다.
- Asynchronous 16-bit timer/counter with four operating modes
- Selectable and configurable clock source
- Two or three configurable capture/compare registers
- Configurable outputs with PWM capability
- Asynchronous input and output latching
- Interrupt vector register for fast decoding of all Timer_A interrupts
몇 가지만 살펴보자.
16비트 비동기 카운터를 사용하며, 네 가지의 모드를 제공한다.
여러 가지 클럭 소스 중 하나를 택한 후 제산을 거쳐 사용할 수 있다.
두 개 혹은 세 개의 캡처/비교 레지스터 쌍을 가지고 있다고 한다. MSP430G2553에서는 Timer A 하나 당 3개씩 가지고 있다.
인터럽트 벡터 레지스터를 지원한다고 한다. 아래 예제 2에 나오듯 이 인터럽트 벡터 레지스터를 통해 해당 인터럽트가 어떤 이벤트에 대한 신호인지를 구분할 수 있다.
Timer A의 다이어그램은 아래와 같다.
클럭 입력, 카운터, TAR, TACCR, 비교기를 거쳐 조건 만족 시 CCIFG에 비트가 설정되는 일련의 과정을 그림을 통해 확인할 수 있다.
Timer A와 관련된 레지스터는 아래와 같다.
- TACTL - Timer_A control
- TAR - Timer_A counter
- TAxCCTLy - Timer_A capture/compare control
- TAxCCRy - Timer_A capture/compare
- TAxIV - Timer_A interrupt vector
타이머는 레지스터마다의 명세가 다소 복잡하다.
Timer A를 설정하기 위한 레지스터이다. 클럭 소스, 제수, 동작 모드, 인터럽트 관련 파라미터들을 설정할 수 있다.
타이머에서 숫자 카운팅 용으로 사용되는 레지스터이다. 0에서부터 65535 사이의 값을 가지며, 카운터를 거칠 때마다 1씩 증가하여 저장된다.
모드에 따라 용도가 다른 레지스터이다.
비교 모드에서는 사용자가 설정한 시간값이 저장된다.
캡처 모드에서는 카운터 정지 시 TAR에서 측정된 측정값이 TACCTL로 복사된다.
으..
타이머 인터럽트 발생 시 어떤 이벤트에 대한 인터럽트인지를 알려주는 레지스터이다. 예를 들어 타이머 오버플로우에 대한 인터럽트가 발생하면 TAIV의 값이 10(0Ah)으로 설정된다.
예제를 다루어보자.
- 타이머 연속 동작에 의한 LED 점멸
- 오버플로우 인터럽트를 이용한 LED 점멸
- 업다운 모드를 이용한 PWM 신호 생성
타이머의 비교 모드를 이용하여 LED를 점멸시키는 예제이다.
SMCLK을 클럭 소스로 사용하며, 카운터가 50000사이클을 돌 때마다 LED를 토글시킨다.
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 50000;
TACTL = TASSEL_2 + MC_2; // SMCLK, contmode
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, Global interrupt enabled
}
#pragma vector=TIMER0_A0_VECTOR // Timer A0 ISR
__interrupt void Timer_A(void)
{
P1OUT ^= 0x01; // Toggle P1.0
CCR0 += 50000; // Add Offset to CCR0
}
위 코드를 실행하면 P1.0에 매핑된 LED가 빠른 속도로 점멸하는 것을 볼 수 있다.
타이머의 오버플로우 인터럽트가 발생하면 LED를 점멸시키는 예제이다.
마찬가지로 SMCLK을 클럭 소스로 사용하며, 오버플로우 인터럽트 발생 시 TA0IV에 값이 10으로 설정되어 switch 문에 의해 LED를 토글시킨다.
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x01; // P1.0 output
TACTL = TASSEL_2 + MC_2 + TAIE; // SMCLK, contmode, interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, Global interrupt enabled
}
#pragma vector=TIMER0_A1_VECTOR // Timer_A1 ISR (TA0IV)
__interrupt void Timer_A(void)
{
switch (TA0IV)
{
case 2: break; // CCR1 not used
case 4: break; // CCR2 not used
case 10: P1OUT ^= 0x01; // overflow
break;
}
}
위 코드를 실행하면 마찬가지로 P1.0에 매핑된 LED가 빠른 속도로 점멸하는 것을 볼 수 있다.
타이머에서 지원하는 모드 중 업다운 모드를 이용하면 PWM 신호를 만들어 출력할 수 있는 듯하다. 예제가 있어 가져왔으며, 실행하면 P1.1 핀에 1kHz의 PWM 주파수가 출력된다고 한다. (SMCLK 1MHz 사용 시.)
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x02; // P1.1 output
P1SEL |= 0x02; // P1.1 option select
CCTL0 = OUTMOD_4; // CCR0 toggle mode
CCR0 = 500 - 1;
TACTL = TASSEL_2 + MC_1; // SMCLK, upmode
__bis_SR_register(CPUOFF); // CPU off
}
코드 실행은 해보았으나 집에 오실로스코프가 없어 파형 확인이 어려웠다. (있는 게 더 이상하지만..)