대학교

마이크로프로세서 - (9) 8비트 타이머/카운터

매 석 2023. 11. 12. 20:03
반응형

타이머/카운터

입력 펄스를 세는 장치를 카운터라고 한다.

일정한 주기의 펄스를 세어 시간을 측정하는 타이머 역할을 수행한다.

클록은 마이크로컨트롤러의 시스템 클록을 기본으로 사용한다.

ATmega128은 0,2번에 8비트, 1,3번에 16비트 타이머/카운터를 사용한다.

8비트 타이머/카운터는 0~255까지 세기를 반복하고 16MHz의 시스템 클록을 기본으로 사용한다.

분주기를 통해 클록의 속도를 늦춰 긴 시간을 측정할 수 있다.

8비트 타이머/카운터 구조

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

위는 0번 아래는 2번 타이머/카운터이다.

클록 MUX 설정 방식과 ASSR 레지스터의 차이점이 있다.

이는 아래에서 다시 설명하겠다.

 

타이머/카운터 레지스터

  1. TCNTn 레지스터 : 현재까지의 펄스 수를 저장

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

오버플로 인터럽트는 TCNTn 레지스터가 0으로 바뀌면서 발생한다.

즉 255까지 채워진 후 0으로 바뀔 때 발생한다.

비교 일치 인터럽트는 TCNTn의 값이 미리 설정된 OCRn 레지스터의 값과 일치할 때 발생한다.

이는 기본값인 255를 128 등으로 줄여서 오버플로 인터럽트의 발생 주기를 설정할 수 있다.

그 결과 비교 일치 인터럽트가 발생할 때 OCn핀을 통해 파형 출력이 가능하다.

2. TCCR0 레지스터 : 타이머/카운터의 세부 동작 설정 레지스터

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

0~2번은 분주비 설정, 3~7번은 비교 일치 인터럽트 설정이다.

파형생성, 비교일치 출력 모드, 비교일치와 동일한 효과 발생 비트가 있다.

3. TIMSK 레지스터 : 인터럽트 활성화 레지스터

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

0번은 오버플로 인터럽트 활성화 비트, 1번은 비교일치 인터럽트 활성화 비트이다.

즉 이러한 개별적 인터럽트 활성화를 0~1번은 0번 타이머/카운터 2~5는 1번 6~7은 2번을 담당한다.

 

오버플로 인터럽트 예제

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

위 예제는 0.5초 간격으로 PB0핀에 연결된 LEX를 점멸하는 것이다.

오버플로 1주기는 펄스 주기*분주비*타이머 비트이다.

즉 위에서는 0.016ms * 1024 * 256 = 약 16ms이다.

이를 32번 발생했을 때 걸리는 시간이 대략 0.5초이다.

그렇기에 분주비, 개별적 인터럽트 허용, 전역적 인터럽트 허용 등의 설정을 하고

PB0의 출력 설정을 해주고 ISR이 발생했을 때 count를 1씩 증가시켜

32가 되면 LED를 키고 끄는 것을 반복한다.

 

 

비교 일치 인터럽트

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

OCRn 레지스터의 값과 TCNTn의 값이 일치하는 경우에 비교 일치 인터럽트가 발생한다.

비교 일치 인터럽트 발생 후 기본적으로 TCNTn 값을 0으로 초기화해야 한다.

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

기본적으로 오버플로 인터럽트와 비슷하지만

비교 일치 기준값과 비교 일치 인터럽트 허용하는 부분과

ISR이 실행될 때 TCNT0=0으로 값을 초기화해 255까지 가는 것을 방지한다.

즉 위 코드는 똑같이 0.5초마다 LED가 점멸하는 코드인데,

비교 일치 기준값을 128로 설정하여 기존 256에서 128로 절반정도 감소하여

ISR이 발생하는 시간도 절반 감소했다. 그렇기에 기존 32의 count를 64로 설정하여 0.5초를 맞춰준다.

 

파형 출력

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

비교 일치 인터럽트가 발생하는 경우 OCn핀으로 파형 출력이 가능하다.

8비트인 0과 2는 1개, 16비트인 1과 3은 3개씩을 가진다.

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

위에서 보았던 TCCR0 레지스터의 WGM 비트에 의해

4가지 모드를 설정할 수 있는데 우선 0번과 2번만 다루려 한다.

0번은 기존의 방식이고 2번인 CTC 모드는 비교 일치 발생 시 TCNT 값을 초기화해준다.

즉 CTC 모드에서는 ISR에서 TCNT0=0이라는 코드가 필요하지 않다.

 

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

정상 및 CTC 모드에서 파형 출력은 COM 비트에 의해 제어된다.

이는 TCCR0의 4,5번 비트이다.

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

아래는 CTC 모드를 사용한 것이다.

그렇기에 ISR에서 TCNT0=0이라는 코드가 없어도 정상적으로 동작한다.

 

ASSR 레지스터

위에서 0번 타이머/카운터에만 있던 레지스터이다.

시스템 클록이 아닌 외부 오실레이터를 클록 소스로 사용 가능하다.

이를 비동기라고 이야기한다. 이는 3번 비트인 AS0을 세트하여 외부 클록을 사용한다.

주로 32.768KHz 시계 클록을 사용한다.

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

기존의 클럭보다 훨씬 크기에 분주비를 조절하여 최대 8초까지도 간격을 조절할 수 있다.

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

외부 오실레이터를 사용하고 분주비를 128로 설정하여 1초마다 LED가 점멸하는 코드를 구현했다.

 

실행 시간 알아내기

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

출처 : ATmega128로 배우는 마이크로컨트롤러 프로그래밍

분주비 64를 기준으로 오버플로 인터럽트 발생 시간을 계산하면

64*256/16000000 = 1ms 24마이크로세크다.

이를 이용해 맨 위 코드에서 ISR이 발생했을 때 해당 시간을 누적해서 더해준다.

millis 함수는 현재까지의 실행 시간을 반환해주는 함수이다.

이를 이용해 main 함수에서 이전 시간과 현재 시간 변수의 차이가 1000 즉 1초를 넘으면

이전 시간에 현재 시간을 저장하고, LED 상태를 반전한다.

즉 1초 주기로 LED를 반전하는 코드이다.