아트메가/이론

아트메가128 타이머/카운터0 overflow interrupt사용하기

원원 2017. 9. 21. 16:18

안녕하세요. 타이머/카운터0에 대해 알아보겠습니다.

이 글에서는 타이머/카운터0번의 overflow interrupt만 보겠습니다.

타이머/카운터란?



타이머/카운터0 사용 흐름 이해하기(overflow)


타이머/카운터0은 8비트 계수기입니다. 즉 0부터 255까지 숫자를 셉니다. 이 숫자는 TCNT0에 저장이 되있습니다.

타이머/카운터는 기본적으로 이 TCNT0의 값에 따라서 이벤트가 발생합니다.

TCNT0가 0부터 255까지 증가하다가 255에서 1이 증가하면 0이됩니다. 이때 overflow interrupt가 발생합니다.

TCNT0가 0부터 x값까지 증가하다가 x=y가 되면 compare match interrupt가 발생합니다.


그럼 이제 TCNT0가 1증가할 때  몇초가 걸릴 것인지 정해야 우리가 원하는대로 타이머/카운터를 사용할 수 있는데요

먼저 아무설정도 하지않는다면 TCNT0의 값이 1증가할때 걸리는시간은 1/16Mhz = 0.0000000625초 입니다. (내부클럭일때)

증가값이 너무 작아서 이걸 조정해줘야하는데요, 조정해주는 친구가 Prescaler입니다.

Prescaler(분주비)표인데요 CS02,CS01,CS00을 111로하면 분주비가 1024인 것을 볼 수있습니다.

분주비를 1024으로 설정하고 TCNT0가 1증가할때 값을 구해보면, 1/16Mhz*1024 = 0.000064초 입니다.

그럼 이제 오버플로우로 인터럽트가 걸리게 한다면 0부터 255까지 TCNT0가 증가하니까 256*0.000064 =0.016384초

0.016384초 마다 오버플로우 인터럽트가 걸리겠네요..

그럼 1초마다 LED를 ON/OFF해주고 싶다면 1/0.016384= 61.03515625번 오버플로우 인터럽트가 발생해야겠네요

61.03니까 61번 오버플로우가 발생한다고하면 1초라고 할 수 있겠네요

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#define F_CPU 16000000UL
 
unsigned char time=0;
int flag = 1;
 
SIGNAL(SIG_OVERFLOW0) // 
{
    if(time==61)
    {
        if(flag)
            PORTA=0xff;
        else
            PORTA=0x00;
        flag=!flag;
 
        time=0;
    }
    else
    {
        time++;
    }
}
 
int main(void)
{
 
   TCCR0= 0x07;
   TIMSK=0x01;
   SREG=0x80;
   DDRA=0xff;
 
    while(1)
    { 
    }
}
 
 
 
cs

LED는 PA0에 연결했고 1초마다 LED가 ON/OFF되는 코드입니다.

11~27번줄까지는 오버플로인터럽트가 발생했을때 실행되는 코드인데요 time이 0부터 61까지 증가했을떄(1초) ON/OFF가 되는것을 볼 수 있습니다.

이제 나머지는 레지스터 설정만 보면 됩니다. 32~34번줄이 레지스터 설정하는 코드인데 이제 타이머/카운터를 설정할때쓰는 레지스터를 알아보겠습니다.



위에서 사용했던 타이머/카운터0 레지스터

TCCR0

7번비트 - FOC0에 1을 입력하면 강제로 compare match가 됩니다. 이렇게 되면 OC0에 신호를 출력할뿐, 인터럽트는 발생시키지않습니다.

6번,3번비트 - Waveform Generation 비트. 여기서는 파형을 안볼것이므로 Normal모드를 선택합니다

5,2번비트 - PWM모드일때 OC0의 상태를 제어하는 비트인데 PWM모드할때 첨부하겠음.

2,1,0번비트 - 분주비 설정비트



TIMSK

타미어/카운터 인터럽트를 set시켜주는 레지스터인데 

1번비트는 카운터/타이머 0번 Output Comare Match Interrupt Enable

0번비트는 카운터/타이머 0번 Overflow Interrupt Enable입니다.

나머지 비트들은 타이머/카운터 1,2 Enable 비트입니다


SREG

SREG레지스터는 외부인터럽트때도 봤겠지만 전역인터럽트 비트를 가지고있는 레지스터입니다. 이 레지스터 7번비트가 전역인터럽트 비트이므로 7번을 set해주면 인트럽트가 허가됩니다.



위에서는 overflow가 발생하면 인터럽트일때 이벤트가 발생하게했는데, 인터럽트를 안 쓰고 해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#define F_CPU 16000000UL
 
unsigned char time=0;
int flag = 1;
 
 
 
int main(void)
{
 
   TCCR0= 0x07;
   SREG=0x80;
   DDRA=0xff;
 
    while(1)
    { 
        if(TIFR&0x01)
        {
            time++;
            TIFR=0x01;
        }
 
        if(time==61)
        {
            if(flag)
                PORTA=0xff;
            else
                PORTA=0x00;
            flag=!flag;
 
            time=0;
        }
    
    }
}
 
 
 
cs
인터럽트가 사라졌고 메인while에 TIFR가 추가된것을 볼 수 있습니다.



TIFR레지스터

이 레지스터 생긴건 TIMSK랑 비슷한데 하는 역할은 Output Comapre Match나 OverFlow가 발생하면 해당비트가 1이 됩니다.

오버플로가 발생( TOV0가 1) -> ( 오버플로인터럽트루틴수행 , TOV0에 1을 넣음 ) 이 두 가지중 한 가지를 수행하면 0이됩니다.

여기선 TOV0에 1을 넣으므로 (25번줄) 0으로 초기화시켜주는 것을 볼 수 있습니다.


다음에는 타이머/카운터0 Compare Match Interrupt를 해보겠습니다