HBE-MCU-Multi 로배우는 마이크로컨트롤러 (AVR 편 ) 마이크로컨트롤러기능 제 6 장타이머와카운터
타이머와카운터 1. 클럭과카운터 2. ATMega128 의타이머 / 카운터 3. 8 비트타이머 / 카운터의일반동작모드 4. 타이머로 LED 점멸시키기 5. 타이머로디지털시계만들기
타이머 / 카운터 타이머와카운터 정확한시간의측정이필요하다.( 자명종과스톱워치 ) 임베디드시스템에서타이머와카운터가시간측정의일을담당한다. 타이머 / 카운터는일정한개수만큼의클럭을세어시간을측정하므로, 정확한시간재기가가능하다. 타이머는필요한시간을미리레지스터에설정하고, 다른작업과병행하게타이머가동작하고, 설정한조건에서인터럽트발생하게함으로써, MCU 의효율을극대화시킬수있다.
클럭과카운터 클럭 시계 일정한시간간격으로 0과 1의값이번갈아나타남 주어진일을순서대로정확한시간에처리하기위해사용 주기 클럭 카운터 0 1 2 3 4 5 6 7 0 1 카운터 클럭을세는장치 카운터크기 카운터의비트수에따라달라짐 : 3 비트카운터 : 2 3 = 8
ATMega128 타이머 / 카운터 타이머와카운터 타이머 : MCU 내부클럭을세는장치 n 동기모드 n 타이머는 MCU 의내부클럭을세어일정시간간격의펄스를만들어내거나일정시간경과후에인터럽트를발생 카운터 : MCU 의외부에서입력되는클럭을세는장치 n 비동기모드 n 카운터는외부핀 (TOSC1, TOSC2, T1, T2, T3) 을통해서들어오는펄스를계수 (Edge Detector) 하여 Event Counter 로서동작
ATMega128 타이머 / 카운터 ATMega128 의타이머카운터 타이머 0~3 모두 4 개의타이머 / 카운터를보유 n 타이머 0,2 : 8 비트타이머로서로기능유사 n 타이머 1,3 : 16 비트타이머로서로기능유사 인터럽트기능 n 오버플로우인터럽트 : 카운터의값이오버플로우되는경우발생 n 출력비교인터럽트 : 카운터값이출력비교레지스터의값과같게되는순간에발생 n 입력캡쳐인터럽트 : 외부로부터의트리거신호에의해서카운터의초기값을입력캡쳐 PWM 출력기능 n Pulse Width Modulation
8 비트타이머 / 카운터 8 비트타이머 / 카운터의특징 4 개의타이머 / 카운터중 0 번과 2 번타이머 / 카운터 PWM 및비동기동작모드를갖는 8 비트업 / 다운 (Up/Down) 카운터 8 비트카운터 : 28 = 256, 즉 0~255 까지셀수있음 10 비트의프리스케일러 (prescaler) 보유 각종인터럽트기능 n 오버플로우인터럽트 (overflow interrupt) n 출력비교인터럽트 (output compare match interrupt) PWM 기능제공 타이머 0 는부가적으로 32.768KHz 의수정진동자를 TOSC1,2 단자에연결해 Real Time Clock 으로사용할수있는기능제공
8 비트타이머 / 카운터 8 비트타이머 / 카운터레지스터 타이머 / 카운터제어레지스터 (TCCRn) 타이머 / 카운터레지스터 (TCNTn) 출력비교레지스터 (OCRn) 인터럽트관련 n 타이머 / 카운터인터럽트플래그레지스터 (TIFR) n 타이머 / 카운터인터럽트마스크레지스터 (TIMSK)
8 비트타이머 / 카운터 프리스케일러 (Prescaler) 고속의클럭을사용하여타이머를동작시킬때나타나는문제를해결하기위해클럭을분주하여더느린타이머클럭을만듦. n 4MHz 클럭을사용하는경우그클럭의주기는 250ns n 이클럭으로 256 까지센다고해도 64us 이하를세는카운터밖에는만들수가없음. 10 비트, 프리스케일러보유 ( 최대 2 10 = 1024 배가능 ) n 프리스케일러를 1024 로하면 4MHz 클럭의타이머클럭은주기가 250ns*1024=256us 가되고, 이클럭을 256 까지센다면 256us*256=65.536ms 크기의타이머를만들수있음.
8 비트타이머 / 카운터 프리스케일러 (Prescaler) 타이머 0 n 클럭소스 : TOSC1에입력된시스템클럭주파수의 1/4미만의외부클럭, TOSC1/TOSC2단자에연결된수정진동자에의해발생된클럭, 내부클럭 n 분주비 : 1, 8, 32, 64, 128, 256, 1024 타이머 2 n 클럭소스 : T2핀으로입력되는외부클럭, 내부클럭 n 분주비 : 1, 8, 64, 256, 1024
8 비트타이머 / 카운터 8비트타이머 / 카운터의일반동작모드 ATmega128는 4가지의타이머동작모드를가짐 가장기본적인동작모드가일반동작모드임. 8비트타이머 / 카운터의동작 동작모드결정. 타이머에사용할클럭소스와프리스케일러결정 원하는타이머의주기및그주기동안의시간을정확히세기위한타이머클럭의수결정. 카운터레지스터의카운터시작값설정 ( 오버플로우인터럽트사용 )
8 비트타이머 / 카운터 8 비트타이머 / 카운터의동작예 동작모드결정 : 일반동작모드 타이머에사용할클럭소스와프리스케일러결정 n 내부클럭 : 7.3728MHz n 프리스케일러 : 1024 n 타이머클럭주파수 : 7372800/1024= 7.2KHz n 타이머클럭주기 : 약 139us (1/7200 = 0.000138888) 원하는타이머의주기및그주기동안의시간을정확히세기위한타이머클럭의수결정. n 1 주기당타이머클럭개수 = 타이머클럭주파수 * 타이머시간 n 만약 10ms 의타이머를만들기원한다면 7200 * 0.01 = 72 카운터레지스터의카운터시작값설정 n 카운터의시작위치를계산하여카운터레지스터를설정 n 카운터시작위치 = 255 - 타이머클럭개수 (255 72 = 183) n 카운터레지스터 (TCNT) 값을 183 으로초기화시키고타이머를동작시키면 72 번증가후 255 값을넘어서인터럽트가걸리게됨.
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) 타이머 / 카운터제어레지스터 n(n=0 or 2) 동작모드, 프리스케일러등타이머 / 카운터의전반적인동작형태를결정 7 6 5 4 3 2 1 0 FOCn WGMn0 COMn1 COMn0 WGMn1 CSn2 CSn1 CSn0 n 비트7 : FOCn n 비트 6,3 : WGM n 비트 5,4 : COM n 비트 2, 1, 0 : CSn
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) FOC(Force Output Compare) n FoC가 1로세트되면출력비교실시 (OC핀작동 ) n FoC가 0로세팅되면출력비교를실시하지않음. WGM(Waveform Generation Mode) n n 타이머 / 카운터의동작모드설정카운터의카운팅방향, 최대카운터값, Waveform Generation 방식등을결정 모드 WGMn1 (CTCn) WGMn0 (PWMn) 타이머 / 카운터동작모드 TOP OCRn의업데이트 TOVn Flag Set-on 0 0 0 0xFF Immediate MAX 1 0 1 PWM, Phase Correct 0xFF TOP BOTTOM 2 1 0 CTC OCRn Immediate MAX 3 1 1 Fast PWM 0xFF TOP MAX
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) COM(Compare Output Mode) n OCn핀의동작을조정 n COMn1/COMn0에따른 Ocn 핀의동작 n Non-PWM 모드 COMn1 COMn0 내용 0 0 normal 포트동작, OCn 연결을끊다. 0 1 Toggle OCn on compare match 1 0 Clear OCn on compare match 1 1 Set OCn on compare match
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) n Fast-PWM 모드 COMn1 COMn0 내용 0 0 normal 포트동작, OCn 연결을끊다. 0 1 예약 1 0 Clear OCn on compare match, set OCn at TOP 1 1 Set OCn on compare match, clear OCn at TOP n PC PWM Mode COMn1 COMn0 내용 0 0 normal 포트동작, OCn 연결을끊다. 0 1 예약 1 0 1 1 up 카운팅일때 Clear OCn on compare match, down 카운팅일때 set Ocn up 카운팅일때 Set OCn on compare match, down 카운팅일때 clear Ocn
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) CSn : 클럭선택 (Clock Select) n 타이머 / 카운터에사용할클럭과프리스케일러를선택 n 타이머 / 카운터 0 CS02 CS01 CS00 설명 0 0 0 클럭소스가없다. 0 0 1 No 프리스케일러 0 1 0 8분주 0 1 1 32분주 1 0 0 64분주 1 0 1 128분주 1 1 0 256분주 1 1 1 1024분주
8 비트타이머 / 카운터 TCCRn(Timer/Counter Control Register n) n 타이머 / 카운터 2 CS22 CS21 CS20 설명 0 0 0 클럭소스가없다. 0 0 1 No 프리스케일러 0 1 0 8분주 0 1 1 64분주 1 0 0 256분주 1 0 1 1024분주 1 1 0 외부클럭의하강에지에서카운터 2동작 1 1 1 외부클럭의상승에지에서카운터 2동작
8 비트타이머 / 카운터 TCNTn(Timer/Counter Register n) 타이머 / 카운터레지스터 n (n 은 0 or 2) n 타이머 / 카운터 n 의 8 비트카운터값을저장하고있는레지스터 n 이레지스터는쓸수도있고읽을수도있다. n 임의의값을써주면타이머의주기를더빠르게할수있다. n 레지스터의값은인터럽트가걸리면자동으로 0 으로클리어되고다시분주된주기마다한개씩값이늘어난다. 7 6 5 4 3 2 1 0 TCNT7 TCNT6 TCNT5 TCNT4 TCNT3 TCNT2 TCNT1 TCNT0
8 비트타이머 / 카운터 TIMSK(Timer Interrupt Mask) 타이머인터럽트마스크레지스터 타이머 / 카운터 0, 타이머 / 카운터 1, 타이머 / 카운터 2 가발생하는인터럽트를개별적으로 enable 하는레지스터 7 6 5 4 3 2 1 0 OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0 비트 1,7 : OCIE0/OCIE2 n 타이머 / 카운터 0/2 의출력비교인터럽트인에이블 비트 0,6 : TOIE0/TOIE2 n 타이머 / 카운터 0/2 오버플로우인터럽트인에이블
8 비트타이머 / 카운터 TIFR (Timer Interrupt Flag Register) 타이머인터럽트프래그레지스터 타이머 / 카운터 0, 타이머 / 카운터 1, 타이머 / 카운터 2 가발생하는인터럽트의플래그를저장하는레지스터 7 6 5 4 3 2 1 0 OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 OCF0 TOV0 비트 1,7 : OCF0/OCF2 n TCNT0/2 레지스터와출력비교레지스터 OCR0/2 값을비교해서, 같으면이비트가 1 로세트되어출력비교인터럽트가발생. 비트 0,6 : TOV0/TOV2 n 타이머 / 카운터 0/2 에서오버플로우가발생하면이비트가 1 로세트되어오버플로우인터럽트가발생.
8 비트타이머 / 카운터 ASSR(ASynchronous Status Register) 비동기상태레지스터 타이머 / 카운터 0 이외부클럭에의하여비동기모드로동작하는경우관련된기능을수행하는레지스터 7 6 5 4 3 2 1 0 - - - - AS0 TCN0UB OCR0UB TCR0UB n 비트 3 (AS0 : ASynchronous timer 0) n n n 비트 2 (TCN0UB : Timer/CouNter0 Update Busy) 비트 1 (OCR0UB : Output Compare Register 0 Update Busy) 비트 0 (TCR0UB : Timer Conter Register 0 Update Busy)
8 비트타이머 / 카운터 SFIOR(Special Function I/O Register) 특수기능 I/O 레지스터 타이머 / 카운터들을동기화하는데관련된기능을담당하는레지스터 7 6 5 4 3 2 1 0 TSM - - - ACME PUD PSR0 PSR321 n 비트 7 (TSM : Timer Synchronization Mode) n 0 : PSR0, PSR321 비트를하드웨어적으로클리어, n 이로인해, 타이머들이동시에카운팅동작을시작한다 n 비트 1 (PSR0 : Prescaler Reset Timer 0) n 1 : 타이머 0 의프리스케일러를리셋 n 비트 0 (PSR321 : Prescaler Reset Timer 321) n 1 : 타이머 1/2/3 의프리스케일러를리셋
8 비트타이머 / 카운터 ATMega128 타이머오버플로우인터럽트프로그램 타이머오버플로우인터럽트프로그램의틀 #include <io.h> #include <interrupt.h> // 인터럽트관련시스템헤더파일 SIGNAL(SIG_OVERFLOW0) /* Timer 0의 Overflow Interrupt 에대한 Interrupt Service Routine 선언 */ { Cli(); /* 인터럽트가발생되었을때실행할명령어세트를선언 */ sei(); } int main(void) { TIMSK = 1 << TOIE0; // 오버플로우인터럽트허용 TIFR =1 << TOV0; // TOV0 Timer/Counter0 overflow flag 클리어 sei(); /* 전체인터럽트 Enable */ for (;;) { /* main loop 명령어세트 */ }
실습 7 : 타이머로 LED 점멸 실습개요 ATmega128 마이크로컨트롤러의타이머기능을이용하여 LED 를점멸시키는실습 타이머를이용하여정확히 1 초마다 LED 가점멸하도록함. 타이머는타이머 / 카운터 0 의일반동작모드를사용 실습목표 타이머0의동작원리이해 타이머0 제어방법의습득 ( 관련레지스터이해 ) 오버플로우인터럽트제어프로그램방법습득
실습 7 : 타이머로 LED 점멸 사용모듈 : MCU 모듈, LED 모듈 MCU 모듈포트 E MCU 모듈 LED 모듈 LED 모듈 Signal
실습 7 : 타이머로 LED 점멸 모듈결선방법 MCU 모듈포트 E 의 PE0 ~PE7 을 LED 모듈의 LED 0 ~ 7 까지연결
실습 7 : 타이머로 LED 점멸 구동프로그램 : 타이머 / 카운터를동작시키기위한사전지식 사용할타이머 / 카운터결정 n 여기서는 8 비트타이머 / 카운터인타이머 / 카운터 0 를사용 동작모드결정 n 여기서는일반동작모드사용 n TCCR 레지스터의 CS 를제외한모든비트들을 0 으로세트. 타이머클럭결정 ( 클럭소스및프리스케일러결정 ) n n n 여기서는내부클럭 (7.3728MHz) 을사용프리스케일러는최대한주기를길게하기위해 1024를사용 ASSR /SFIOR는디폴트, TCCR0의 CS비트를 111 로설정 타이머주기결정 n n n 1초를만들기위해 10ms을타이머주기로결정인터럽트는 10ms마다발생, 인터럽트가 100번발생하면 1초로간주 10ms를맞추기위해서세어야하는카운터개수를계산하고그카운터개수를만족시키기위한 TCNT 초기값을 TCNT0에넣음. (183) 인터럽트인에이블 n TIMSK 레지스터를설정하여오버플로우인터럽트를 Enable 하고, TIFR 레지스터의 Timer/Counter0 overflow flag 를클리어
실습 7 : 타이머로 LED 점멸 구동프로그램 : 소스분석 Timer_led.c 1) #include<avr/io.h> #include<avr/interrupt.h> unsigned char LED_Data = 0x00; unsigned char timer0cnt=0; 2) SIGNAL(SIG_OVERFLOW0); //Timer0 Overflow0 ISP int main(){ 3) DDRE = 0xFF; // 포트 E 를 (0~7 비트까지모두 ) 출력포트로사용
실습 7 : 타이머로 LED 점멸 4) TCCR0 = 0x07; /* 0~7비트까지의모든 register중에서 0~2까지의레지스터를사용하여출력한다. 1024prescaler (Timer/Counter0 Control Register: Timer/Count0의동작을설정하고프리스케일러를설정하는등의기능을수행한다.) */ TCNT0 =0xff - 72; /* (1 / (7.3728 Mhz / 1024 prescaler )) * 72=>0.01s 0.01s를얻기위한카운트값 (Timer/Count0 Register: Timer/Count0의 8비트카운터값 을저장하고있는레지스터이다.) */ TIMSK = 1 << TOIE0; // 오버플로우인터럽트허용 TIFR =1 << TOV0; // TOV0 Timer/Counter0 overflow flag 클리어 5) sei(); while(1){
실습 7 : 타이머로 LED 점멸 6) PORTE = LED_Data; // LED_Data를포트 E로보낸다. } return 0; } 7) SIGNAL(SIG_OVERFLOW0){ cli(); TCNT0=0xff - 72; timer0cnt++; if(timer0cnt == 100){ // 0.01s * 100 = 1s 1초를얻기위한카운트횟수 LED_Data++; timer0cnt=0; } sei(); } 인터럽트서비스루틴
실습 7 : 타이머로 LED 점멸 실행결과
실습 8 : 타이머를이용한디지털시계 실습개요 타이머를이용하여디지털시계의기능을설계 Array-FND 모듈에마이크로컨트롤러출력포트를연결하고, 클럭을이용하여일정카운트기능을수행 타이머 / 카운터 0 의일반모드동작을사용한다 편이상시계는초와분까지만표시 실습목표 타이머 / 카운터활용방법의습득 ( 관련레지스터이해 ) 디지털시계 ( 초 / 분 ) 구현방법이해
실습 8 : 타이머를이용한디지털시계 사용모듈 : MCU 모듈, ArrayFND 모듈 MCU 모듈포트 G MCU 모듈포트 E MCU 모듈 ArrayFND 모듈 ArrayFND 모듈 Signal
실습 8 : 타이머를이용한디지털시계 모듈결선방법 포트 E 의 PE7~PE0 를 Array FND 모듈의 A~H 까지연결. 포트 G 의 PG3~PG0 는 Array FND 모듈의 C3~C0 포트에연결.
실습 8 : 타이머를이용한디지털시계 구동프로그램 : 사전지식 타이머를이용하여디지털시계 타이머로 LED 점멸하기예제와거의유사 시계표시를위해 Array-FND를사용 타이머를이용하여정확히 1초를카운트
실습 8 : 타이머를이용한디지털시계 구동프로그램 : 소스분석 Timer_digitalclock.c 1) #include<avr/io.h> #include<avr/interrupt.h> #include<util/delay.h> enum{c0,c1,c2,c3}; unsigned char FND_DATA_TBL[]={0x3F,0X06,0X5B,0X4F,0X66,0X6D,0X7C,0X 07,0X7F, 0X67,0X77,0X7C,0X39,0X5E,0X79,0X71,0X08,0X80}; // 표시문자에대한 FND 문자표 unsigned char time_s=0, time_m=0,timer0cnt=0; 2) void print_fnd(unsigned charselcx, unsigned char data); /* 원하는 FND 포트에 data 출력 */ 3) SIGNAL(SIG_OVERFLOW0); //Timer0 Overflow0 ISP int main(){
실습 8 : 타이머를이용한디지털시계 4) DDRE = 0xFF; /* data port 0~7 비트까지의모든 register 를사용하여출력한다. (Data Direction Register) */ PORTE = 0x00; /* 0~7 비트까지의모든 register 를사용하여입력한다. */ DDRG = 0x0F; PORTG = 0x0F; /* control port 0-3 PIN 0~4 비트까지의 register 중에서 0~3 비트까지의 register 를 사용하여출력한다. */ /* 0~4 비트까지의 register 중에서 0~3 비트까지의 register 를 사용하여입력한다. */ 5) TCCR0 = 0x07; /* 0~7비트까지의모든 register중에서 0~2까지의레지스터를 사용하여출력한다. 1024prescaler (Timer/Counter0 Control Register: Timer/Count0 의동작을설정하고프리스케일러를 설정하는등의기능을수행한다.) */ TCNT0 =0xff - 80; /* (1 / (7.3728 Mhz / 1024 prescaler )) * 80=>0.011s 0.011s 를얻기위한카운트값 (Timer/Count0 Register: Timer/Count0 의 8 비트카운터값을 저장하고있는레지스터이다.) */ TIMSK = 1 << TOIE0; // 오버플로우인터럽트허용 TIFR =1 << TOV0; //TOV0 Timer/Counter0 overflow flag 클리어
실습 8 : 타이머를이용한디지털시계 6) sei(); while(1){ 7) print_fnd(c3, time_s%10); //4번째 COM 에 1초단위출력 _delay_ms(1); print_fnd(c2, time_s/10); _delay_ms(1); print_fnd(c1, time_m%10); _delay_ms(1); print_fnd(c0, time_m/10); _delay_ms(1); } return 0; } // 3 번째 COM 에 10 초단위출력 // 2 번째 COM 에 1 분단위출력 // 1 번째 COM 에 10 분단위출력
실습 8 : 타이머를이용한디지털시계 8) SIGNAL(SIG_OVERFLOW0){ cli(); TCNT0=0xff - 80; timer0cnt++; if(timer0cnt == 90){ // 0.011s * 90 = 1s //1초를얻기위한카운트횟수 if(time_s >= 59){ time_m++; time_s = 0; } else time_s++; 인터럽트서비스루틴 if(time_m > 59){ time_m = 0; } timer0cnt =0; } sei(); }
실습 8 : 타이머를이용한디지털시계 9) void print_fnd(unsigned char selcx, unsigned char data){ switch(selcx){ case C3: // 4번째 FND ( 좌측기준 ) PORTG &= 0xF0; // 하나씩만입력하기위해서그전의내용을초기화시킴 PORTG = 0x07; // 포트 G의 G0을사용하여 C3로출력 break; case C2: //3번째 FND PORTG &= 0xF0; // 이전내용초기화 PORTG = 0x0B; // 포트 G의 G1을이용하여 C2로출력 break; case C1: //2번째 FND PORTG &= 0xF0; PORTG = 0x0D; // 포트 G의 G2를이용하여 C1으로출력 break; case C0: //1번째 FND PORTG &= 0xF0; PORTG = 0x0E; // 포트 G의 G3를이용하여 C0로출력 Break;
실습 8 : 타이머를이용한디지털시계 9) default: PORTG &= 0xF0; PORTG = 0x0F; // 포트 G의 G4를사용하지않는다. break; } if(selcx == C1 && time_s%2 == 0) // C1에일정하게. 을찍는다 PORTE =FND_DATA_TBL[data] 0x80; else PORTE =FND_DATA_TBL[data]; }
실습 8 : 타이머를이용한디지털시계 실행결과