반응형



용어 정의

BOTTOM - 카운터가 0이 되었을 때를 의미.


MAX – 카운터가 0xFF(=255)에 도달했을 때를 의미


TOP 

TOP값은 0xFF(MAX) 또는 OCR0 레지스터에 저장된 값으로 지정할 수 있다.

카운터가 TOP값과 똑같거나 더 커진 경우를 의미한다.



일반 모드

TCCR0 레지스터의 WGM00 비트와 WGM01 비트가 0으로 설정된 경우이다.



TCNT0 레지스터는 카운터에서 값을 직접 읽거나 쓸 수 있게 해주는 레지스터이다.


일반 모드에서 카운팅은 항상 증가하는 방향으로 이루어 진다.


8비트로 표현할 수 있는 최대값인 0xFF(=255)를 초과하면 다시 bottom(=0)부터 카운팅을 시작한다.  TCNT0가 0이 되는 순간 TIFR 레지스터의 TOV0 비트가 1로 설정된다.


타이머/카운터 오버플로우 인터럽트와 같이 사용되면, TIFR 레지스터의 TOV0 플래그 비트는 자동으로 0으로 클리어된다.


TIMSK 레지스터의 TOIE0 비트가 1로 설정되고 Status 레지스터의 I비트가 1로 설정되었을 때 타이머/카운터0 오버플로우 인터럽트가 활성화된다.




프리스케일러 선택은 TCCR0레지스터의 CS02, CS01, CS00 비트에 의해서 결정된다.



아래처럼 회로를 구성하고 프로그램 코드를 테스트한다. 



사용중인 크리스탈의 값 F_CPU = 16Mhz이고 8비트 타이머(최대값 255)를 사용한다면 만들 수 있는 최소 딜레이값은 0.016ms이다. 계산과정은 다음과 같다.


주기 = 1/주파수 = 1/16000000 Hz = 0.0000000625 s = 0.0000625 ms


타이머 카운터 = 필요한 딜레이 시간 / 클록 시간 주기 – 1

255 = X / 0.0000625 ms – 1

X = 256 * 0.0000625 ms = 0.016 ms



1 ms를 만들고 싶다면... 위에서 계산한 순서대로 계산해보면 된다.


F_CPU 그대로 사용한다면

16MHz => 0.0000625 ms

1ms/0.0000625ms –1 = 15999=> 8비트 표현 범위를 넘어섬..


프리스케일러로 8을 사용한다면

16MHz / 8 = 16000000/8 = 2000000Hz => 0.0000005 s = 0.0005ms

1ms/0.0005ms –1 = 1999 => 8비트 표현 범위를 넘어섬..


프리스케일러 64를 사용한다면

16Mhz / 64 = 16000000/64 = 250000Hz => 0.000004 s = 0.004ms

1ms/0.004ms –1 = 249 => 8비트 카운터로 사용가능


프리스케일러 256을 사용한다면

16Mhz / 256 = 16000000/256 = 62500Hz => 0.000016 s = 0.016ms

1ms/0.016ms-1=61.5 => 소수점이 있음


프리스케일러 1024를 사용한다면...

16Mhz / 1024 = 16000000/1024 = 15625Hz => 0.000064 s = 0.064ms

1ms/0.064ms-1=14.625 => 소수점이 있음..



위에서 계산한 결과를 이용하여 1ms마다 오버플로우 인터럽트가 발생하도록 설정해놓았다.

프르스케일러로 64를 사용하게 되며 TCNT0의 시작값은 256-249인 7이 된다.

249는 위에서 계산한 결과 값이다.




따라서 total_overflow_count값이 1000이 될때마다 1초가 되므로 

LED는 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
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * 8bit_timer_example.c
 *
 * Created: 2016-06-17
 * Author : webnautes
 */ 
#define F_CPU 16000000UL
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
volatile uint16_t total_overflow_count;
 
 
ISR(TIMER0_OVF_vect)
{
    total_overflow_count++;
    TCNT0 = 7;
}
 
int main(void)
{
    DDRB |= (1<<DDB3); //LED용
 
    //프리스케일러로 64를 선택
    TCCR0 |= (1<<CS02);
 
    //카운터 초기화 256-249
    TCNT0 = 7;
 
    //타이머/카운터 오버플로우 인터럽트 활성화
    TIMSK |= (1<<TOIE0);
 
    //전역 인터럽트 활성화
    sei();
 
    total_overflow_count = 0;
 
 
    /* Replace with your application code */
    while (1
    {
        if ( total_overflow_count == 1000 ) //1초마다 LED 켜짐
        {
            total_overflow_count = 0;
            PORTB |= (1<<PB3);
            _delay_ms(10);
        }
        else PORTB &= (~(1<<PB3));
 
            
    }
}
 
 
cs


문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts