레이블이 direct register access인 게시물을 표시합니다. 모든 게시물 표시
레이블이 direct register access인 게시물을 표시합니다. 모든 게시물 표시

2016년 1월 27일 수요일

Arduino Uno에서 digitalWrite()와 직접 레지스터 제어의 속도 차이

먼저 아두이노 우노에서 가장 기본 예제인 blink를 실행시켜 출력파형을 오실로 스코프로 확인해 보면 다음과 같다.

void setup()
{
  pinMode(10, OUTPUT);
}

void loop()
{
  digitalWrite(10, HIGH);
  digitalWrite(10, LOW);
}



대략 digitalWrite()를 한번 실행하는데 6.8us정도의 시간이 걸린다.

위의 코드를 동일한 기능을 하지만 digitalWrite() 함수를 사용하지 않고 ATmega328의 레지스터를 직접 제어하도록 하면 코드는 다음과 같다.

void setup() { 
  DDRB |= (1<<2);}

void loop() {
  PORTB |= (1<<2);
  PORTB &= ~(1<<2);
}

위의 코드를 실행한 결과를 오실로 스코프로 확인한 결과는 다음과 같다.




이 경우 약 120ns정도의 시간이 걸리게 된다. (약 57배 speed up)
단 위의 파형에서 출력이 HIGH인 구간과 LOW인 구간이 비대칭인 이유는 loop함수를 빠져나갔다가 다시 호출되는데 필요한 오버헤드로 인해 LOW->HIGH구간에 포트 조작 이외의 작업이 추가되었기 때문이다.

void setup() { 
  DDRB |= (1<<2);}

void loop() {
  while (1) {
    PORTB |= (1<<2);
    PORTB &= ~(1<<2);
  }
}

코드를 위와 같이 수정하여 loop() 함수 exit/enter에 따른 오버헤드를 없애 준 결과는 다음과 같다.


아직도 아주 약간 비대칭이기는 해도 거의 차이가 없어진 걸 확인할 수 있다.

참고삼아 아래 코드를 실행해 측정해 본 digitalRead() 함수의 실행시간은 다음과 같다.

void setup() {
  DDRB |= (1<<2);
  pinMode(11,INPUT);
}

void loop()
{
  PORTB |= (1<<2); 
  boolean button = digitalRead(11);
  PORTB &= ~(1<<2);
}

digitalRead() 함수를 호출하는 경우 대략 5.2us 정도의 시간이 소요된다.