이번 수업 시간에는
타이머/카운터(TC-Timer Counter)와 AIC(Advanced Interrupt controller)를 사용해
1초간격으로 LED를 깜빡이게 하였습니다.
- 먼저 TC 와 AIC에 대해 간략히 알아보고 본문으로 넘어가겠습니다
AT91SAM7S256의 타이머/카운터(TC)는, ① 0~2까지 3개의 채널을 가지며, 이들은 서로 독립적으로 동작합니다. ② 타이머 카운터의 레지스터(TC_RC)는 최대 16비트 까지의 이진값(65535)을 가질 수 있습니다. ③ 또한 상태 레지스터(TC_SR)를 호출하면 레지스터가 초기화 됩니다. ④ TC는 주파수 측정, 시간 간격 측정, 시간 지연, 펄스 발생, PWM 출력, 이벤트 카운트 등의 기능을 수행할 수 있습니다. ⑤ TC의 레지스터 맵핑을 살펴보면 TC0 TC1 TC2 각각의 채널을 제어하는 레지스터가 따로 존재하기 때문에 그에 해당하는 레지스터를 사용해야 합니다. ⑥ 단, TC_BCR과 TC_BMR 레지스터는 3개 채널 공용레지스터입니다. ⑦ 채널 모드 레지스터(TC_CMR)가 있어 MCK(마스터클럭)를 분주(2, 8, 32, 128, 1024)한 신호를 입력받을 수 있습니다. |
AT91SAM7S256의 AIC(Advanced Interrupt Controller)는, ① 32개의 인터럽트 소스 ② 0부터 7까지 8레벨의 우선순위 제어 예) AIC_SMR[TC0] = (0 << PRIOR); <-- 우선순위 최하 ③ 개별적인 인터럽트 허용 ④ 벡터형 인터럽트 처리 |
자, 이제 소스를 보면서 공부해 봅시다^^
소스의 주석을 통해 설명하고 있으니, 주석을 잘 관찰하시기 바랍니다~*
#include "timer.h" static volatile unsigned int uiTic; // Timer_Handler 함수 호출을 카운트, 1m초 void Timer0_Init(void) { PMC_PCER = 1 << TC0; // PMC_PCER(Peripheral Clock Enable Register)에 타이머카운터 장치 활성화, P204, P33 // TC0(타이머카운터 0)에 클럭이 공급된다.
// 1. 시작 : 타이머 클럭 비활성화 ------------------ TC0_CCR = 1 << CLKDIS; //카운터 클럭 비활성화 명령(CLKDIS)을 Enable // 2. 시작 : 타이머 인터럽트 비활성화 ------------- TC0_IDR = (1 << COVFS)|(1 << LOVRS)|(1 << CPAS)|(1 << CPBS) |(1 << CPCS)|(1 << LDRAS)|(1 << LDRBS)|(1 << ETRGS); // 타이머 인터럽트 비활성화(TC_IDR 설정)
TC0_SR;// 타이머카운터 상태 레지스터 초기화(TC_SR 읽기) TC0_CMR = (TIMER_CLOCK4 << TCCLKS) | (1 << CPCTRG); /*TC0_CMR(채널 모드 레지스터)에서 TCCLKS(Clock Selection)에 3을 넣어 분주비 128(TIMER_CLOCK4) 설정 | RC 비교방식 트리거 활성화*/ TC0_RC = 375; // MCK divided by 128 => 375000Hz, 1CK = (about)2.67us [TC_RC(Register C)설정] // 한마디로 1ms에 인터럽터를 발생시키기 위해 375로 설정 // 3. 시작 : 타이머 카운터 0 인터럽트 비활성화 ------ AIC_IDCR = 1 << TC0; // 인터럽트 비활성화(AIC_IDCR) = Enable(1) << 타이머 카운터 0(TC0) AIC_SVR[TC0] = (volatile unsigned int)Timer_Handler; /*AIC_Source Vector Register = 타이머 카운터 0 인터럽트 핸들러 등록 여기서 Vector 레지스터는 인터럽트가 발생하면 점프하게 될 함수(ISR:인터럽트 서비스 루틴)의 주소만을 저장할 수 있다. 함수 전체를 저장할 수 있으면 좋겠지만, 그러기엔 ARM 레지스터의 용량이 너무 작다. ◎ Vector 가 뭔지 궁금해 하시는 분들을 위해 - 우리의 ARM은 폴링형 인터럽트와 vector형 인터럽트 등 인터럽트 처리방법 중에 vector형 인터럽트 처리 방식을 사용한다. 1. Polling 형 인터럽트 - 폴링은 투표, 개표 라는 뜻이다. 즉 CPU가 소프트웨어적으로 보드에 인터럽트를 낼수있는 하드웨어들을 차례대로 검사하는 방식이다. 하드웨어가 간단하고 저렴하지만, 인터럽트를 낼수있는 하드웨어 갯수 증가에 따라 속도가 느려진다. 이후 인터럽트가 검출된 장치를 처리한다. 여기서 "처리한다" 를 ISR(Interrupt Service Rutine)이라고 한다. 2. vector 형 인터럽트 - cpu가 소프트웨어적으로 하드웨어들을 검사하는것이 아니라, 인터럽트를 발생시킨 장치가 cpu에 ISR(우리가 만든 핸들러 함수)의 시작 번지를 제공하면 cpu가 이것을 먼저 처리하는 방식. 이 ISR들은 기본적으로 interrupt vector에 저장되어 있고 더 나아가 사용자가 ISR을 설정해주고 싶으면 Interrupt Handler를 작성/등록(AIC_SVR[TC0])해주면 된다. 하드웨어가 복잡하고 비싸지만, 빠르고, 장치 갯수에 상관없이 언제든지! 서비스를 제공한다. AT91SAM7S256, atmega2560 등 에서는 이방식을 사용한다. AIC_SMR[TC0] = (0 << PRIOR)|(3 << SRCTYPE); /* TC0 인터럽트 소스 모드 레지 = 우선순위레벨(Priority Level)을 0 | 여기서 만약, 인터럽트 두개가 동시에 발생하면 ? polling 방식은 순차적으로 장치를 검사하기 때문에 그 순서대로 우선순위를 정하지만 vector 방식은 인터럽트 우선순위를 제어할 수 있는 레지스터(AIC_SMR)가 존재하여, 레지스터에 값을 집어넣어 우선순위를 정한다. [출처] [AVR] Interrupt|작성자 태희로그 [출처] [AVR] Interrupt|작성자 태희로그 Interrupt Source Type(SRCTYPE)를 High level Sensitive로 설정*/ AIC_ICCR = 1 << TC0; // 타이머 카운터 0 인터럽트 클리어(TC0) TC0_IER = 1 << CPCS; /* 타이머 카운터 인터럽트 활성화 레지스터 = RC 비교 인터럽트만 활성화*/ // 2. 끝 : 타이머 인터럽트 비활성화 --------------- AIC_IECR = 1 << TC0; // 타이머 카운터 0 인터럽트 활성화(AIC_IECR, TC0) // 3. 끝 : 타이머 카운터 0 인터럽트 비활성화 ------- TC0_CCR = 1 << CLKEN; // 타이머 클럭 활성화(TC_CCR, CLKEN) // 1. 끝 : 타이머 클럭 비활성화 ------------------ TC0_CCR = 1 << SWTRG; // 타이머 시작(TC_CCR, SWTRG) } void Timer_Handler(void) { TC0_SR; //핸들러가 호출되면 현재 인터럽트가 발생된 상태이기 때문에 //다음 인터럽트가 발생할 수 있도록 상태 레지스터 초기화 ++uiTic; return; } void ms_Delay(unsigned int uims) { uiTic = 0; while(uims > uiTic); //이 함수를 종료하려면 uims를 기다려야 한다 // uiTic은 1ms마다 증가하므로 uims에 1000을 넣으면 //약 1초를 기다려야 반복문이 종료된다. } |
헤더파일과 메인소스는 첨부하지 않아도 이해할 수 있으므로 생략하도록 하겠습니다.
위의 소스를 보면서 이해하셨다면, 좋겠지마~는 아닐 경우를 대비해
여기서 끝내지 않고 조금더 이해하기 쉽도록 그림으로 설명해 볼까요?^^
|
위의 그림에서 인터럽트가 발생하는 시점은 : 우리가 소스에서 TC0_RC = 375; 를 함으로써 0.001초마다 한번씩 인터럽트가 발생합니다.
그러므로 main함수에서 Timer_Init()을 호출하면 약 0.001초 마다 인터럽트가 발생하게 되는 것입니다.
그 인터럽트 발생 횟수를 저장하기 위해서 전역변수(static volatile unsigned int uiTic;) 하나를 핸들러 함수 안에 만들어 놓았습니다.
제 글을 읽고 조금이나마 이해하시는데 도움이 됐으면~ 하는 바램입니다~
모두들! 즐공^^ 개선해야 할 점 댓글로 달아주세용~
'코스웨어 > 13년 스마트컨트롤러' 카테고리의 다른 글
[인터럽트 요청시 사용되는 용어 명확한 설명]by 문남경 (5) | 2013.05.22 |
---|---|
5월 20일 AIC_init()만들기 -송시혁 (6) | 2013.05.22 |
5월 21일 AIC_Handdler 함수만들기-송시혁 (4) | 2013.05.22 |
2013.05.20_[타이머카운터복습/인터럽트/풀업풀다운저항]_김성엽 (12) | 2013.05.22 |
5월 13일 수업 정리 - 임기준 (11) | 2013.05.20 |
2013.5.14 (화) Review - C언어 13장 do - while , 조건부컴파일 [손초롱] (8) | 2013.05.20 |
[수업정리]130510_김창훈 (9) | 2013.05.20 |
5월 9일 정리 노트 - 이규남 (7) | 2013.05.20 |