블로그 이미지
래머
오늘도 열심히 개발하는 개발자입니다.

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2015. 2. 9. 21:58 아두이노

아두이노 타이머 인터럽트를 공부하다가 외국의 어느사이트에서 찾은 정보를 안되는 영어 실력이지만 살짝 번역해 보았습니다.

타이머 인터럽트 사용시 도움이 될듯합니다.
문제시 삭제 하겠습니다.

원문 : http://www.instructables.com/id/Arduino-Timer-Interrupts/step2/Structuring-Timer-Interrupts/


영어 실력이 좋지 못한 관계로 의역 및 오역이 있을 수 있습니다.


Picture of Structuring Timer Interrupts
IMG_9676 copy
IMG_9682 copy
Screen Shot 2013-04-17 at 2











Timer setup code is done inside the setup(){} function in an Arduino sketch.

타이머 셋업 코드는 아두이노 스케치의 setup() 함수 내에서 끝난다.

The code involved for setting up timer interrupts is a little daunting to look at, but it's actually not that hard.  I pretty much just copy the same main chunk of code and change the prescaler and compare match register to set the correct interrupt frequency.
포함된 타이머 인터럽트 셋팅 코드가, 보기에 조금은 어려울수도 있지만, 사실 전혀 어렵지 않다. 단지 올바른 인터럽트의 주파수를 설정하기 위해 프리스케일러와 비교 매치값 설정을 변경하는 동일한 메인 조각코드들을 조금 복사 했을 뿐이다.  
The main structure of the interrupt setup looks like this: 

인터럽트셋업의 주된 구조는 다음과 같다 : 

//http://www.instructables.com/id/Arduino-Timer-Interrupts/<br>void setup(){cli();//stop interrupts, 인터럽트를 멈춤//set timer0 interrupt at 2kHz, 타이머0을 2KHz로 설정  TCCR0A = 0;// set entire TCCR0A register to 0(TCCR0A레지스터를 0으로설정)  TCCR0B = 0;// same for TCCR0B(TCCR0B도 같음)  TCNT0  = 0;//initialize counter value to 0(카운터값을 0으로초기화)  // set compare match register for 2khz increments(비교매치 레지스터값을 2kHz증가로 설정)  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)  // turn on CTC mode(CTC 모드 켜기)  TCCR0A |= (1 << WGM01);  // Set CS01 and CS00 bits for 64 prescaler(CS01과 CS00비트를 64프리스케일러로 설정 )  TCCR0B |= (1 << CS01) | (1 << CS00);     // enable timer compare interrupt(타이머 비교 인터럽트를 활성화시킴)  TIMSK0 |= (1 << OCIE0A);//set timer1 interrupt at 1Hz(타이머1을 1Hz로 설정)  TCCR1A = 0;// set entire TCCR1A register to 0  TCCR1B = 0;// same for TCCR1B  TCNT1  = 0;//initialize counter value to 0  // set compare match register for 1hz increments  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)  // turn on CTC mode  TCCR1B |= (1 << WGM12);  // Set CS10 and CS12 bits for 1024 prescaler  TCCR1B |= (1 << CS12) | (1 << CS10);    // enable timer compare interrupt  TIMSK1 |= (1 << OCIE1A);//set timer2 interrupt at 8kHz  TCCR2A = 0;// set entire TCCR2A register to 0  TCCR2B = 0;// same for TCCR2B  TCNT2  = 0;//initialize counter value to 0  // set compare match register for 8khz increments  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)  // turn on CTC mode  TCCR2A |= (1 << WGM21);  // Set CS21 bit for 8 prescaler  TCCR2B |= (1 << CS21);     // enable timer compare interrupt  TIMSK2 |= (1 << OCIE2A);sei();//allow interrupts}//end setup

Notice how the value of OCR#A (the compare match value) changes for each of these timer setups.  As explained in the last step, this was calculated according to the following equation:


각각의 타이머 설정을 위해 OCR#A(비교매치값)를 어떻게 설정하는지는 , 이전의 단계에서 설명했던것처럼, 다음의 방정식으로 계산된다.

compare match register = [ 16,000,000Hz/ (prescaler * desired interrupt frequency) ] - 1


remember that when you use timers 0 and 2 this number must be less than 256, and less than 65536 for timer1

기억해야할것은, 당신이 타이머 0과 2를 사용한다면, 이 값이 256보다 작아야 하며, 타이머1일경우 65536보다 작아야한다.

Also notice how the setups between the three timers differ slightly in the line which turns on CTC mode:

CTC모드를 켜기 위해 3개의 타이머 사이의 차이점은 다음과 같다 : 


TCCR0A |= (1 << WGM01);//for timer0
TCCR1B |= (1 << WGM12);//for timer1
TCCR2A |= (1 << WGM21);//for timer2
This follows directly from the datasheet of the ATMEL 328/168.


이것은 Atmel 328/168의 데이터시트를  직접적으로 얻었다.

Finally, notice how the setup for the prescalers follows the tables in the last step (the table for timer 0 is repeated above),

마지막으로, 이전 단계의 테이블에 나왔던 프리스케일러의 설정을 어떻게 하냐면(타이머 0의 것은 위에서 다시 보여주고 있다),
TCCR2B |= (1 << CS22);  // Set CS#2 bit for 64 prescaler for timer 2
TCCR1B |= (1 << CS11);  // Set CS#1 bit for 8 prescaler for timer 1
TCCR0B |= (1 << CS02) | (1 << CS00);  // Set CS#2 and CS#0 bits for 1024 prescaler for timer 0

Notice in the last step that there are different prescaling options for the different timers.  For example, timer2 does not have the option of 1024 prescaler.

이전 단계의 표에서 각 타이머들의 프리스케일링 옵션은 다르다. 예를들어  타이머2는 1024프리스케일러 옵션을 가지고 있지 않다.

The commands you want to execute during these timer interrupts are located in the Arduino sketch encapsulated in the following:

이들 타이머의 인터럽트 동안에 당신이 실행하기 원하는 명령들은 아두이노 스케치에 다음과 같이 요약되어 있다:
ISR(TIMER0_COMPA_vect){  //change the 0 to 1 for timer1 and 2 for timer2(타이머 1을위해서 0은 1로 타이머2인경우 0을 2로 바꿔라)
   //interrupt commands here
}
This bit of code should be located outside the setup() and loop() functions.  Also, try to keep the interrupt routine as short as possible, especially if you are interrupting at a high frequency.  It may even be worth addressing the ports/pins of the ATMEL chip directly instead of using the digitalWrite() and digitalRead() functions.  You can find more info about that here.

이 코드 조각은 setup()과 loop()의 밖에 위치한다. 특히 인터럽트가 고주기로 실행되는경우 인터럽트 루틴에 머무는 시간을 가능한 짧게 하도록 노력해라. 아트멜칩의 포트와 핀을 digitalWrite() 와 digitalRead()함수를 사용하기 보다는 직접적으로  어드래싱하는것도 한층 가치 있는일이다. 여기(here)에서 좀더 많은 정보를 찾을 수 있다.


Example- the following sketch sets up and executes 3 timer interrupts:

예제 - 다음의 스케치는 3개의 타이머 인터럽트를 설정하고 실행한다.
 

//timer interrupts//by Amanda Ghassaei//June 2012//http://www.instructables.com/id/Arduino-Timer-Interrupts//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. 이프로그램은 무료소프트웨어다; 당신은 이것을 무료소프트웨어 토대로 배포된 GNU 일반 공중 라이센스 하에서 수정/재배포 가능하다; 라이센스버전3 또는 이후의 버전(당신이 선택한)
 **///timer setup for timer0, timer1, and timer2.//For arduino uno or any board with ATMEL 328/168.. diecimila, duemilanove, lilypad, nano, mini...//this code will enable all three arduino timer interrupts.//timer0 will interrupt at 2kHz//timer1 will interrupt at 1Hz//timer2 will interrupt at 8kHz//storage variablesboolean toggle0 = 0;boolean toggle1 = 0;boolean toggle2 = 0;void setup(){    //set pins as outputs  pinMode(8, OUTPUT);  pinMode(9, OUTPUT);  pinMode(13, OUTPUT);cli();//stop interrupts//set timer0 interrupt at 2kHz  TCCR0A = 0;// set entire TCCR2A register to 0  TCCR0B = 0;// same for TCCR2B  TCNT0  = 0;//initialize counter value to 0  // set compare match register for 2khz increments  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)  // turn on CTC mode  TCCR0A |= (1 << WGM01);  // Set CS01 and CS00 bits for 64 prescaler  TCCR0B |= (1 << CS01) | (1 << CS00);     // enable timer compare interrupt  TIMSK0 |= (1 << OCIE0A);//set timer1 interrupt at 1Hz  TCCR1A = 0;// set entire TCCR1A register to 0  TCCR1B = 0;// same for TCCR1B  TCNT1  = 0;//initialize counter value to 0  // set compare match register for 1hz increments  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)  // turn on CTC mode  TCCR1B |= (1 << WGM12);  // Set CS12 and CS10 bits for 1024 prescaler  TCCR1B |= (1 << CS12) | (1 << CS10);    // enable timer compare interrupt  TIMSK1 |= (1 << OCIE1A);//set timer2 interrupt at 8kHz  TCCR2A = 0;// set entire TCCR2A register to 0  TCCR2B = 0;// same for TCCR2B  TCNT2  = 0;//initialize counter value to 0  // set compare match register for 8khz increments  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)  // turn on CTC mode  TCCR2A |= (1 << WGM21);  // Set CS21 bit for 8 prescaler  TCCR2B |= (1 << CS21);     // enable timer compare interrupt  TIMSK2 |= (1 << OCIE2A);sei();//allow interrupts}//end setupISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)  if (toggle0){    digitalWrite(8,HIGH);    toggle0 = 0;  }  else{    digitalWrite(8,LOW);    toggle0 = 1;  }}ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)  if (toggle1){    digitalWrite(13,HIGH);    toggle1 = 0;  }  else{    digitalWrite(13,LOW);    toggle1 = 1;  }}  ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz toggles pin 9//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)  if (toggle2){    digitalWrite(9,HIGH);    toggle2 = 0;  }  else{    digitalWrite(9,LOW);    toggle2 = 1;  }}void loop(){  //do other things here}


The images above show the outputs from these timer interrupts.  Fig 1 shows a square wave oscillating between 0 and 5V at 1kHz (timer0 interrupt), fig 2 shows the LED attached to pin 13 turning on for one second then turning off for one second (timer1 interrupt),  fig 3 shows a pulse wave oscillating between 0 and 5V at a frequency of 4khz (timer2 interrupt).

위의 이미지는 이들 타이머 인터럽트들로 부터의 출력을 보여준다. Fig1은 1KHz의 0 ~ 5V로 진동하는 직각파를 보여준다(타이머 0 인터럽트),

fig2는 LED가 결합된 13번핀이 1초동안 켜지고 1초동안 꺼지는 것을 보여주며(타이머1 인터럽트), fig3은 4KHz로 진동하는 0 ~ 5V의 펄스 웨이브를 보여준다(타이머2 인터럽트).


posted by 래머