Arduino MCU Register ATmega328P

아두이노 UNO의 MCU ATmega328P Register Set-up


아래의 low-level motor control을 하기 위해서 set up에 관련된 Arduino 코드이다. 아래의 setup에 대해서 code analysis를 해보자~
=======================================================================
 // put your setup code here, to run once:
  TCCR1A = 0; // set entire TCCR1A register to 0
  TCCR1B = 0; // same for TCCR1B
  TCNT1  = 0; //initialize counter value to 0
  OCR1A = 62500 / _accIncrementFrequency; // compare match register (16MHz/256)/ Frequency, int _accIncrementFrequency = 100; //Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  TIMSK1 &= ~(1 << OCIE1A); // disable compare interrupt
=======================================================================

우선 timer/counter register의 diagram을 보면 아래와 같다. 이 diagram의 흐름대로 이해하면 될 것 같다.


16 bit timer/counter register block diagram in Atmega328p

추가적으로 Counter Unit Block Diagram 이다. TCNT1은 16 bit counter이다.





1. Register 용어 정리


TCCR1A: Timer/Counter Control Registers - 8 bit registers
TCCR1B: Timer/Counter Control Registers - 8 bit registers
TCNT1: 16 bit Timer/Counter, 실질적인 Timer 동작값이 여기에 저장된다.
OCR1A: Output Compare Registers

* Each bit in register has a name, such as WGM12 and CS12.
WGM12: TCCR1B에 존재하는 bit이다. bit 위치는 4번째에 위치 index 3이다.
CS12: Clock select bit
TIMSK1: Timer/Counter Interrupt Mask Register, timer interrupt 활성화/비활성화용으로 쓰인다.
TIFRx: Timer/Counter Interrupt Flag Register이다. Pending Timer Interrupt 용도인지 표시한다.
CTC: Clear Timer on Compare modes
OCIE1A: TIMSK Register에 존재하는 bit이며 위치는 bit 1이다. 의미는 Output Compare A Match Interrupt Enable이다. 이 bit가 1로 쓰여지면, Status Register에 있는 I-flag가 set이 되며, Timer/Counter1 Output Compare B Match Interrupt가 enable된다. 

2. 아두이노 타이머는 주기적으로 반복되는 동작의 경우, 정확한 시간 뒤 특정한 코드가 실행될 수 있도록 타이머를 사용하게 된다. 타이머는 시간관련된 이벤트를 위해 설계된 함수이다.



3. 아두이노의 시간 관련 함수들 리스트


- delay(), millis(), micros(), delayMicroseconds(), PWM 함수인 analogWrite() 및 tone(), noTone() 함수들 및 서보모터 라이브러리 등이 내부적으로는 타이머를 사용


4. Timer (or Counter)는 Arduino에 장착된 MCU에 내장되어 있다. 그리고 그 MCU 내장되어 있는 특별한 Register를 이용해서 Timer의 동작방식과 주기 등을 프로그래밍 할 수 있다.




5. Arduino의 MCU인 ATmega는 보통 3개의 timer를 가지고 있다.


timer 0: 8 bit timer (2^8 resolution)
timer 1: 16 bit timer (2^16 resolution)
timer 2: 8 bit timer ((2^8 resolution)


6. 모든 Timer는 Arduino 시스템 clock에 따른다. 


일반적으로 시스템 clock frequency가 16MHz로 가정하고 아래의 내용을 보자. 시스템마다 다르니 MCU의 system clock frequency 확인 요망.


7. timer는 특별한 timer register에 의해 설정된다. 


Arduino Firmware에서는 모든 Timer가 1kHz frequency 로 맞춰져 있고, interrupt가 활성화되어 있다.


8. Arduino Uno Case - ATmega328P MCU


timer 0: 8 bit timer, 시간 관련 함수에 사용된다. 그래서 timer 0 register 를 변경하면 delay(), millis(), micros()와 같은 시간관련 함수들도 영향을 받는다.

delay(): Pauses the program for the amount of time (in milliseconds) specified as parameter

millis(): Returns the number of milliseconds passed since the Arduino board began running the current program.

micros(): Returns the number of microseconds since the Arduino board began running the current program.

timer 1: 16 bit timer, Servo motor library (Servo)가 timer 1을 사용한다.

timer 2: 8 bit timer, tone() 함수 등에 사용한다.


9. Timer Register를 통해 Timer 동작을 바꿀 수 있다. Register는 Arduino system 영역에서 사용하는 설정 값으로 보면된다.



- TCCR1A Register Description



TCCR1A = 0; // set entire TCCR1A register to 0
위의 예제 코드에 의하여 일단 8 bit setting은 처음에 00000000으로 설정된다.

- TCCR1B Register Description 



TCCR1B = 0; // same for TCCR1B
위의 예제 코드에 의하여 일단 8 bit setting은 처음에는 00000000으로 설정된다.

TCCR1B |= (1 << WGM12);   // CTC mode
위의 예제 코드에 의하여 WGM13, WGM10과 WGM11은 0으로 setting되어 있고, WGM12만이 1로 셋팅되어 있으므로 CTC 모드에 들어간다.
현재 8bit setting은 00001000이다.



Waveform Generation Mode Bit Description

TCCR1B |= (1 << CS12);    // 256 prescaler
다시 위의 코드로 인해 clock select bit이 달라진다. CS12는 1이 되고, CS11과 CS10은 0이 되므로, clk_I/O/256 from prescalar 상태가 된다.
최종적으로 TCCR1B bit setting은 00001100이 된다.


Clock select Bit Description


10. CTC - Clear Timer on Compare Match (CTC) Mode란? (데이터 시트 페이지 125)


OCR1A나 ICR1 Register가 counter resolution을 결정한다.

OCR1A = 62500 / _accIncrementFrequency; // compare match register (16MHz/256)/ Frequency, int _accIncrementFrequency = 100; //Hz
위의 코드로 인해 OCR1A는 625로 설정된다.
625의 binary number는 00000010 01110001이다.
OCR1A의 register 구조는 아래와 같다. 그래서 OCR1AH는 00000010이고, OCR1AL은 01110001이다. 이 OCR1A register는 TCNT1과 비교하여, 그 매치가 Output Compare Interrupt를 만들어내고, OC1x pin에서 waveform을 만들어낸다.




OCR1A/B는 double buffered Output Compare Registers이며, timer/counter 의 값을 비교하는 역할을 한다. counter value in TCNT1가 OCR1A와 매치가 되면 counter는 0이 된다.

Output Compare와 관련된 diagram은 아래와 같다.





TCNT1  = 0; //initialize counter value to 0
현재 counter value는 0으로 셋팅되어 있다. 16 bit setting은 000000000 00000000이다. Counter는 증가하면서 OCR1A (625, 00000010 01110001)와 매칭되면, 다시 0으로 reset된다.

TCNT1 Register Description은 아래와 같다.






11. TIMSK - Timer/Counter Interrupt Mask Register


8 bit register이다.

TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
위의 코드에 의하면, TIMSK1은 OCIE1A가 1로 바뀌어서, 00000010이 된다.

TIMSK1 &= ~(1 << OCIE1A); // disable compare interrupt
다시 위의 코드에 의하면, TIMSK1은 ~(1<<OCIE1A)가 11111101이고, &= operator에 의해서 다시 00000000으로 disable된다.




12. CPU 동작 Clock에 따라 Timer Frequency가 결정된다.



- CPU 동작 주기는 16MHz
- 최대 타이머 카운트는 16비트의 경우 65536, 8비트의 경우 256이다.
- 선택한 Prescalar는 앞서서 TCCR1B register에 의해서 256으로 정해졌다.
TCCR1B |= (1 << CS12);    // 256 prescaler
- CPU 주기가 16MHz이므로 prescalr 256을 나누면, 62500이라는 값이 산출된다.
- 이 값을 다시 _accIncrementFrequency 100Hz로 나누면, 625라는 값이 나온다. 이 값은 결국 OCR1A의 값으로 설정되어서 추후에 TCNT1가 매치되어서 waveform 생성한다.
_accIncrementFrequency = 100;
- 결과값인 625가 최대 타이머 카운트인 65536(이 경우 16bit counter이므로)과 비교했을 때, 작으므로 적합하다. 만약에 최대 타이머 카운트보다 클 경우 더 큰 prescalar를 TCCR1B에서 설정해주어야 한다.


13. Timer modes - CTC Mode

CTC모드에서는 타이머 카운터가 compare match register (이 경우 625) 값에 도달할 때 타이머가 다시 0으로 reset된다.



counter value (TCNT1)이 compare match인 OCR1A(625)까지 증가하다가, match 되는 순간 TCNT1은 clear된다. OC1A를 통한 waveform generation 의 경우, TCCR1A에 있는 COM1A1:0 bits 가 1로 설정되어 있어야 한다. 이 경우에는 TCCR1A 전체가 0으로 셋팅되어있으므로, 생략한다.

참조:
- http://www.hardcopyworld.com/ngine/aduino/index.php/archives/1181
- https://www.arduino.cc/reference/en/
- ATmega328p datasheet

Comments

Popular posts from this blog

AVR for Arduino/Atmel MCU

UART Communication

RS-485 Communication 구현