-
타이머 카운터Arduino/Atmel Studio 2021. 1. 7. 11:26
타이머는 8비트 타이머와 16비트 타이머가 있다.
8비트 타이머에 대해 알아보자.
16Mhz = 16000000hz <- Atmega328p의 클락이다.
동작을 맞춰주기 위해서 클락이 필요하다.
16Mhz / 1024 = 15625 <- 1초당 발생 펄스 수이다. <- 초당 발생되는 클럭이라고 정의할 수 있다
1024는 분주율이다.
분주비는 8, 64, 256, 1024를 선택할 수 있다. 그중에 1024를 많이 쓴다.
분주율을 사용하는 이유는 1초 / 16Mhz를 하면
하나의 펄스가 만들어지는데 걸리는 시간이 나노 세컨드 단위로 나온다.
즉, 값이 너무 작아서 분주율을 적용한 것이다.
그리고 8비트가 timer 발생 비트의 수라고 한다면, 8비트로 표현할 수 있는 가지 수는 2^8 = 256이다.
16Mhz / 1024 / 256 = 약 61 <- 1초에 펄스를 61번 발생한다는 의미.
256을 61번 돌아야 15625hz가 된다.
61은 그 단위가 hz이다. ( 펄스가 초당 61번 발생. )2로 나누는 이유는 1초가 아닌 0.5초를 표현하기 위함.
이에 대한 근사치로 61은 64로 둬서 이를 2로 나누면 32가 된다.
그리고 1 / 61을 해서 하나의 펄스를 만드는데 걸리는 시간이다. ( 주기 )
1 / 61 = 0.016초이다.소스 내용
더보기/* 타이머 카운터를 이용한 LED의 ON/OFF */ #define F_CPU 16000000UL // 16MHz #include <avr/io.h> #include <avr/interrupt.h> int count = 0; // 오버플로우 개수 카운터 int state = 0; // LED 상태 /* Interrupt Service Routine */ ISR(TIMER0_OVF_vect) // 인터럽트는 오버플로우가 발생했을 때, 호출된다. { /* 0.5초마다 LED의 ON/OFF를 제어 */ count += 1; // 8bit timer에 1024 분주율을 적용하면, 약 61hz가 된다. // 대략 0.5초는 32hz가 발생 if ( count == 32 ) // 0.5초가 지나면 { count = 0; state = !state; if ( state ) PORTB = 0xff; else PORTB = 0x00; } } int main(void) { // 1. 디지털 12번핀을 출력으로 사용하고 타이머 카운터를 설정 // D12번핀과 LED와 220옴 저항을 연결. DDRB = 0x10; PORTB = 0x00; // 2. TCCR설정(분주비 1024), TIMSK(인터럽트 허용) // TCCR0B |= ( 1 << CS02 ) | ( 1 << CS00 ); // TOIE0는 레지스터(0-base 기준)의 1번째 비트를 의미 TCCR0B |= ( 1 << CS02 ); TCCR0B |= ( 1 << CS00 ); TIMSK0 |= ( 1 << TOIE0 ); // 해당 비트를 1로 설정해서 인터럽트 허용 sei(); // 전역 인터럽트 허용 while (1) { } }
16비트 타이머를 사용해서 0.5초마다 LED를 On/Off해보자.
16비트에서는 8192가 16비트로 표현할 수 있는 가지 수이다.
8비트 카운터를 사용하냐 16비트 카운터를 사용하냐에 따라 OCR값이 달라진다.
16비트를 사용할 때는 최대 가지수 2^16 = 65536
15625hz / 65536 = 0.249hz소스 내용
더보기/* 값이 같아질 때, 인터럽트가 발생한다. 인터럽트의 발생에 따라 5V가 인가되거나 0V가 인가된다. 아두이노의 9번핀에 LED를 연결한다. */ #define F_CPU 16000000UL // 16MHz #include <avr/io.h> #include <avr/interrupt.h> /* Interrupt Service Routine */ ISR(TIMER1_COMPA_vect) { TCNT1 = 0; } int main(void) { // 타이머1을 이용하여 비교하는 내용 // 1. 타이머1의 컨트롤 레지스터를 분주율 1024로 설정(101로 설정) TCCR1B |= ( 1 << CS10 ); TCCR1B |= ( 1 << CS12 ); // 2. 카운터랑 설정값을 비교하는 설정 OCR1A = 0x2000; // 0x2000 = 0010 0000 0000 0000 = 1 * 2^13 = 8192 // 0x2000는 십진수로 8192이며, 이는 0.5초를 의미한다. TCCR1A |= ( 1 << COM1A0 ); // 3. 출력핀을 설정 DDRB |= ( 1 << PORTB1 ); // OCA1핀을 의미(아두이노의 D9번핀) // 4. 타이머 마스크 설정 TIMSK1 |= ( 1 << OCIE1A ); // 비교하여 인터럽트 발생 sei(); // 전역 인터럽트 허용 while (1) { } }
서보 모터를 제어하는 내용을 알아보자.
소스 내용
더보기/* 서보모터를 아두이노의 9번핀에 연결한다. */ #define F_CPU 16000000UL // 16MHz #include <avr/io.h> #include <util/delay.h> #define PULSE_MIN 1000 // 최소 펄스 지점 #define PULSE_MAX 5000 // 최대 펄스 지점 void InitTimer(void) { TCCR1A |= ( 1 << WGM11 ); TCCR1B |= ( 1 << WGM12 ) | ( 1 << WGM13 ); TCCR1B |= ( 1 << CS11 ); // 분주율 8, 2Mhz ICR1 = 40000; // 20ms 주기 TCCR1A |= ( 1 << COM1A1 ); // 비 반전 모드 DDRB |= ( 1 << PB1 ); // 디지털 9번핀 } int main(void) { InitTimer(); int i, j; while (1) { // 서보 모터를 조금씩 움직이는 내용 for ( i = PULSE_MIN; i <= PULSE_MAX; i += 20 ) { OCR1A = i; _delay_ms(50); } for ( j = PULSE_MAX; j >= PULSE_MIN; j -= 20 ) { OCR1A = j; _delay_ms(50); } } }
'Arduino > Atmel Studio' 카테고리의 다른 글
ADC ( 조도 센서와 포텐시오미터의 값을 읽기 ) (0) 2021.01.06 UART 통신 (0) 2021.01.05 Microchip Studio를 통해 아두이노에 프로그램 업로드 하기 (버튼, 피에조 부저 제어) (0) 2021.01.04 Microchip Studio를 통해 아두이노에 프로그램 업로드 하기 (LED 제어) (0) 2020.12.31 Atmega Firmware (0) 2020.12.30