안녕하세요. 타이머/카운터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 |
이 레지스터 생긴건 TIMSK랑 비슷한데 하는 역할은 Output Comapre Match나 OverFlow가 발생하면 해당비트가 1이 됩니다.
오버플로가 발생( TOV0가 1) -> ( 오버플로인터럽트루틴수행 , TOV0에 1을 넣음 ) 이 두 가지중 한 가지를 수행하면 0이됩니다.
여기선 TOV0에 1을 넣으므로 (25번줄) 0으로 초기화시켜주는 것을 볼 수 있습니다.
다음에는 타이머/카운터0 Compare Match Interrupt를 해보겠습니다
'아트메가 > 이론' 카테고리의 다른 글
아트메가128 타이머/카운터0 CTC 모드 알아보기 (0) | 2017.09.27 |
---|---|
아트메가128 타이머/카운터0 compare match interrupt사용하기 (0) | 2017.09.26 |
아트메가128 타이머/카운터란? (0) | 2017.08.06 |
아트메가128 센서제어하기(ADC제어) 2편 (5) | 2017.07.04 |
아트메가128 usart통신하기(3) 컴퓨터 (1) | 2017.07.03 |