2011년5월11일...타이머/카운터 복습, CTC모드, 응용실습문제2
복습 (reviewing) |
16Mhz는 1초당 16,000,000번의 클럭이 발생되므로 카운터로 계수하기 힘든 큰 수이다.
그래서 1/1000로 나누어 1ms당 16,000번만 계수하도록 정하고,
프리스케일로 64분주하면 1/64이 되므로 250번만 계수하면 된다. 즉, 8bit 타이머/카운터로 계수가 가능해진다.
<타이머 관련 레지스터>
1. TCCR0 – 타이머/카운터 제어.
2. TCNT0 - 0~255까지 계수가능. 시스템에 의해 자동으로 증가함.
3. TIMSK – 인터럽트 마스크(선택)
prescaler |
인터럽트 서비스 루틴 (ISR) |
TCNT0의 값이 256일 때 오버플로우 인터럽트가 발생하므로,
타이머/카운터0 오버플로 인터럽트 서비스루틴에서 TCNT0의 값을 다시 바꾸어 주어야 한다.
예) prescaler = 64, TCNT0 = 6 (@1ms)
prescaler = 8, TCNT0 = 56 (@0.1ms)
여기서 함수를 호출하여 TCNT0의 값을 초기화하였다. 이렇게 함수를 호출하면 오래 걸리니 보통 명령문만 쓴다.
그리고 시간변수를 1증가 시키는 명령도 추가해야한다.
타이머/카운터0 CTC모드 (비교매치인터럽트) |
○ OCR0레지스터 추가
○ OCR0와 TCNT0의 값을 계속 비교 후 같으면 → TCNT0 = 0가 됨.
<설 정>
① TCCR0 - CTC모드, 프리스케일러 1/64 (WGM01 = 1, CS02 = 1)
② OCR0 – CPU_CLOCK / TICK_PER_SEC / PRESCALER = 250
③ TIMSK – 비교매치 입터럽트 마스크 활성 ( 1 << OCIE0 or 2)
○ TCNT0와 OCR0를 계속 비교하여 같으면 인터럽트 발생.
TCNT0는 인터럽트 발생시 자동으로 0으로 초기화되니 오버플로우 인터럽트 보다 정밀도가 높다.
(인터럽트 서비스 루틴내에서 TCNT0를 초기화하면 그 명령 수행시간만큼 오차가 발생함.)
SIGNAL(SIG_OUTPUT_COMPARE0)
{
시간변수증가;
}
이런식으로 TCNT0초기화를 빼면 된다.
★앞으로 시간지연이 필요한 경우 delay( )를 쓰지말고 sleep( )를 사용할 것.
타이머/카운터 응용실습문제2 |
1. 난수를 발생하여 해당값을 반복적으로 LED에 표시.
ON/OFF를 각각 0.5초간 유지
2. 위의 소스를 수정하여 각각의 LED 하나에만 랜덤으로
ON/OFF 하도록 하시오.
※ main( )를 제외한 다른 함수는 모두 1번과 같으므로 생략함.
○ srand( )에 seed값을 넣어줘야 하나 PC와 달리 AVR은 RTC(실시간시계)가 없어 불특정한 값을 avr-gcc에선 넣어 줄 수 없다.
그래서 스위치를 누를 경우 srand( )가 호출되고 메인 프로그램이 시작되도록 해야한다.
(사람이 스위치를 언제 누를지 알 수 없음 + TCNT0는 계속 증가되고 초기화됨 = 불특정값)
참조 (Reference) |