※ 주의사항 ※
본 블로그는 수업 내용을 바탕으로 제가 이해한 부분을 정리한 블로그입니다.
본 내용을 참고로만 보시고, 틀린 부분이 있다면 지적 부탁드립니다!
감사합니다😁
안녕하세요!!
오늘은 아래와 같은 내용을 확인해보겠습니다.
16비트 타이머/카운터
오버플로 인터럽트
비교 일치 인터럽트
파형 출력
1. 16비트 타이머/카운터 개요
1-1. 8비트 타이머/카운터 vs 16비트 타이머/카운터
- ATmega128A는 4개의 타이머/카운터를 가지고 있다.
- 0번과 2번의 타이머는 8비트고, 1번과 3번의 타이머는 16비트이다.
- 16비트 타이머의 구조는 8비트 타이머에 비해 상대적으로 복잡하지만 사용하는 기능은 비슷하다.
1) 8비트 타이머와 16비트 타이머의 대표적 차이점 2가지!
첫째!! 비교 일치 인터럽트가 8비트는 1개, 16비트는 3개 이다.
둘째!! 16비트 타이머/카운터에는 입력 캡처 인터럽트가 있다.
2) 오버플로 인터럽트의 사용방법은 동일하나 셀수 있는 펄스의 갯수가 더 많아졌다.
(8비트 : 256개 - 레지스터 1개 사용/ 16비트 : 65536개 - 레지스터 2개 사용 )
1-2. 인터럽트 종류
1) 오버플로 인터럽트
- 8비트는 0 ~ 255까지 즉, 256개 카운터 가능
(현재까지 센 펄스를 저장하는 레지스터 1개 - TCNT0)
- 16비트는 0 ~ 65535까지 즉, 65536개 카운터 가능
(현재까지 센 펄스를 저장하는 레지스터 2개 - TCNT1 = TCNT1H + TCNT1L)
2) 비교 일치 인터럽트
- 3개의 비교 일치 인터럽트를 사용 가능 (8비트는 1가지)
- 3개의 서로 다른 출력 핀에서 파형 출력이 가능
3) 입력 캡처 인터럽트
- 특정 사건이 발생한 경우 현재 카운터 값인 TCNT1 레지스터 값을 저장
※ 입력 캡처 인터럽트는 자주 사용하지 않는 기능이기에 본 과정에서는 생략하였습니다.
(추후 주말을 이용해서 독학의 시간을 가져보겠습니다.🤔)
※ 타이머/카운터 레지스터의경우 1개의 레지스터에 8비트와 16비트 타이머/카운터 관련 비트가 섞여있는 경우가 있습니다. 아래의 레지스터 관련 설명글은 16비트 타이머/카운터 중에서도 1번 타이머에 해당하는 레지스터와 비트만 설명하겠습니다.
2. 16비트 타이머/카운터 오버플로 인터럽트
2-1. 오버플로 인터럽트 레지스터
1) TCNT1 레지스터
- ATmega128A는 8비트의 CPU를 제공하기 때문에 레지스터 크기 역시 8비트이다.
따라서 8비트 레지스터 2개를 묶어서 사용한다. (TCNT1 = TCNT1H + TCNT1L)
- 0 ~ 65535 까지 셀수 있는 16비트 레지스터이다.
- 분주하지 않는 경우 4.096ms 간격의 인터럽트가 발생한다.
- 256으로 분주하는 경우 약 1초 간격으로 인터럽트가 발생한다.
2) TCCR1B 레지스터
- 타이머/카운터는 별도의 설정을 하지 않으면 Default 상태는 Disable
- 타이머/카운터를 Enable 하기 위해서는 TCCR1B레지스터에서 분주비를 설정하여야 한다.
(1) ICNC1, ICES1 비트 (7번, 6번 비트) : 입력 캡처 인터럽트에서 사용하는 비트
(2) WGM13, WGM12 비트 (4번, 3번 비트) : 비교 일치 인터럽트에서 사용하는 비트
(아래 '3-1. 비교 일치 인터럽트 레지스터'에서 설명 예정)
(3) CS12, CS11, CS10 비트( 2번, 1번, 0번 비트) : 분주비를 설정하는 비트
※ CS1n 비트 값에 따른 분주비
CS12 | CS11 | CS10 | 설명 |
0 | 0 | 0 | 클록 소스 없음 (타이머/카운터 정지) |
0 | 0 | 1 | 분주비 1 |
0 | 1 | 0 | 분주비 8 |
0 | 1 | 1 | 분주비 64 |
1 | 0 | 0 | 분주비 256 |
1 | 0 | 1 | 분주비 1,024 |
1 | 1 | 0 | T1 핀의 외부 클록을 사용하여 하강 에지에서 동작 |
1 | 1 | 1 | T1 핀의 외부 클록을 사용하여 상승 에지에서 동작 |
3) TIMSK 및 ETIMSK 레지스터 (Timer / counter Interrupt MaSk Register)
- 오버플로 및 비교 일치, 입력 캡처 인터럽트를 활성화 하기 위한 레지스터
※ 1번 타이머에 관련된 인터럽트 활성화 비트라고 하더라도 2개의 레지스터에 분포되어 있음
- 5개의 인터럽트에 대해 각각의 활성화 비트가 존재한다.
(1) TOIE1 비트 : 오버플로 인터럽트 활성화
(2) OCIE1A ~ OCIE1C 비트 : 비교 일치 인터럽트 활성화
(3) TICIE1 비트 : 입력 캡처 인터럽트 활성화
2-2. 오버플로 인터럽트 관련 예제 - 1 : LED 점멸
1) 코드 설명
- Line 6 ~ 11 : 1번 Timer의 오버플로 ISR에 해당되는 함수부
0x0000에서 0xFFFF까지 펄스를 센 후에 해당 루틴(LED 상태 반전)을 1번 실행한다.
- Line 18 : 16비트 타이머의 분주비를 256으로 설정
즉, 16Mhz / 256[분주] * 65536 = 1.048576 → 1.04초마다 오버플로 ISR이 실행된다.
- Line 19 ~ 20 : 인터럽트가 실행되기 위한 필수 조건인 전연 인터럽트와 개별 인터럽트가 활성화 된다.
2-3. 오버플로 인터럽트 관련 예제 - 2 : '정확히' 1초에 한번 LED 점멸
- 해당 문제는 교수님께서 직접 내신 문제로서 교재에 있는 예제는 정확히 1초마다 혹은 0.5초마다 인터럽트가 발생하는것이 아닌 근사값이 나온다고 합니다. 따라서 오버플로 인터럽트의 개념을 이해하고 분주율과 반복횟수를 파악해서 정확히 1초에 한번 LED를 점멸하는 프로그래밍을 짜보라고 하셨습니다!!
1) 동작 설명
- 왼쪽 코드와 오른쪽 코드의 동작은 동일하게 1초에 한번 LED가 점멸하는 프로그래밍 입니다.
- 하지만 왼쪽은 인터럽트가 0.001초에 한번 발생하고 그 횟수를 1000번 측정하여서 LED를 제어하고
오른쪽은 인터럽트가 1초에 한번 발생해서 ISR 안에 LED가 제어하는 코드가 포함되어 있습니다.
2) 코드 설명
- 왼쪽 : 64분주, 초기값 0XFF06, ISR 1000번 수행 후 LED 제어
(64[분주] x 250 ) / 16000000[Hz] = 0.001[s] → 0.001[s] x 1000 = 1[s] )
- 오른쪽 : 1024분주, 초기값 0XC2F6, ISR 1번 수행 후 LED 제어
(1024 x 15625) / 16000000[Hz] = 1[s] )
※ 추가로, Line 109에서 초기값을 ISR 내 뿐만아니라 main문 안에도 넣어 주었는데 그 이유는 처음 ATmega128A에 전원이 들어왔을때도 1초에 한번 ISR을 발생시키기 위함이다. 만약 해당 라인을 생략할 경우 첫 동작은 0X0000 ~ 0XFFFF 즉 65536번 수행 후(4.19초 후)에 ISR이 발생한다. (← 중요한 내용은 아니지만 코딩에 있어서 버그(?) 같은 문제로 확인 차 짚고 넘어갑니다!!)
3. 16비트 타이머/카운터 비교 일치 인터럽트
3-1. 비교 일치 인터럽트 레지스터
1) OCR1x( x = A, B, C) 레지스터
- 비교 일치 인터럽트에서 사용될 비교값을 저장해주는 레지스터 (OCR1x = OCR1xH + OCR1xL)
- 16비트의 값을 저장하기 위해 2개의 8비트 레지스터를 조합하여 사용한다. (TCNT1 레지스터와 개념 동일)
2) TCCR1A, TCCR1B 레지스터
(1) COM1x1, COM1x0 비트(x = A, B, C)
- 7번부터 2번까지 각각 2개의 비트가 비교 일치시 파형 생성을 제어하는 비트
- 00 : OC1A 핀으로 데이터가 출력되지 않으며, OC1A 핀은 일반적인 범용 입출력 핀으로 동작
- 01 : 비교 일치가 발생하면 OC1A 핀의 출력은 반전 된다.
- 10 : 비교 일치가 발생하면 OC1A 핀의 출력은 LOW 값으로 바뀐다.
- 11 : 비교 일치가 발생하면 OC1A 핀의 출력은 HIGH 값으로 바뀐다.
(2) WGM1n(n = 1 ~ 4) 비트 (Wave Generation Mode)
- 파형 생성 모드를 결정하는 비트 (CTC, 고속 PWM, 위상 교정 PWM 등)
- 총 16개의 모드 중에 PWM과 관련된 모드는 아직 배우지 않은 내용으로 보류하고 0번, 4번, 12번 모드만 PWM과 관련 없는 모드에 해당된다.
- 0번 : 기본적인 모드
(0번 모드의 경우 TCNT1의 초기값을 사용자가 필요에 따라 직접 설정하였다.)
- 4번 : CTC 모드로써 비교 일치가 발생한 후에 TCNT1 레지스터의 값을 자동으로 0으로 설정한다.
- 12번 : 4번과 동일하나 비교 일치가 발생하는 기준이 ICP1핀에 입력의 변화가 발생하였을때 발생한다.
3-2. 비교 일치 인터럽트 관련 예제 - 1 : LED 점멸
1) 코드 설명
- Line 12 : CTC모드로 설정해주지 않았기 때문에 TCNT1 레지스터의 초기값 설정
- Line 20 : 비교 일치값 설정 (0x7FFF로 설정하면 약 0.52초 간격으로 LED가 점멸한다)
3-3. 비교 일치 인터럽트 관련 예제 - 2 : 서로 다른 주기를 갖는 LED 점멸
1) 동작 설명
(1) 1번 TIMER에서 총 4개의 인터럽트를 1초마다 한번씩 발생시킨다.
- TCNT1의 레지스터 값이 0x0000에서 0xFFFF까지 올라가면서 0x3FFF(약 0.25초)에서 비교 일치 A 인터럽트 발생
- 0x7FFF(약 0.5초)에서 비교 일치 B 인터럽트 발생, 0xBFFF(약 0.75초)에서 비교 일치 C 인터럽트 발생
- 0xFFFF(약 1초)에서 오버플로 인터럽트를 발생
(2) 인터럽트가 발생될때마다 LED의 값이 '반전'된다.
(3) TCNT1의 값을 초기화 해주지 않았기 때문에 TCNT1 레지스터는 0x0000에서 0xFFFF까지 선형적으로 증가한다.
2) Volatile 명령어에 대해
- 최적화를 방지하기 위한 개념으로 ISR내에 사용되는 변수는 Volatile이란 명령어를 변수 선언할때 붙혀준다.
- 기본적으로 전역변수를 선언하면 하드웨어에서 SRAM에 변수의 공간을 만들어서 용량을 차지하게 된다.
- 하지만 최적화할때 전역 변수를 선언해도 해당 변수를 사용하지 않는다면 변수가 컴파일 할때 삭제될수가 있다.
- 즉, Volatile은 최적화를 해도 해당 변수를 무조건 사용한다는 개념으로 해당 변수의 공간을 만드는 효과를 준다.
(즉, 용량이 충분하다면 ISR내에 사용되는 변수는 무조건 volatile을 붙혀주는게 좋다)
3-4. 파형 출력
1) 코드 설명
- Line 132 ~ 133 : B포트의 5번핀을 출력으로 설정한다.
비교 일치 인터럽트가 발생했을경우 해당 파형을 보기 위해선 특정한 포트의 핀에서만 파형이 출력된다.
- Line 135 : 1024분주했을때 비교 일치 인터럽트의 발생 주기를 1초로 하기 위해 목표 설정값 입력
- Line 137 : 1024 분주 설정
- Line 138 : 비교 일치 A 인터럽트가 발생하면 해당 출력을 반전시킨다.
- Line 140 : 비교 일치 A 인터럽트 Enable
※ B포트의 5번 핀에서 출력되는 파형을 오실로스코프로 측정해본 결과 위의 사진과 같이 일정한 펄스를 가지는 파형을 출력한다.
댓글