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 정도의 시간이 소요된다.

댓글 2개:

  1. 정말 필요한정보를 잘 봤습니다.
    질문 드려도될까요..?ㅎㅎ
    1. digital read 함수 호출하는 경우 5.2us가 소요된다고하셨는데, 레지스터를 직접제어하면 몇초 정도 걸리는지 알 수 있을까요??

    2. digital read 함수의 시간측정은 어떻게 진행하셨나요?

    3. 레지스터를 제어하는 코딩도 아두이노 스케치에서 바로 가능한가요??

    답글삭제
    답글
    1. 1. 레지스터 제어는 따로 시간 측정을 해 보지 않았지만 PIN 레지스터를 읽는것이므로 write와 거의 비슷할겁니다.
      2. digitalRead를 호출하기 전에 출력핀을 high로 만들고 호출, 호출에서 리턴되면 출력핀을 low로 만들어 오실로스코프에서 출력핀 파형을 확인한거죠. 맨 아래 사진에서 펄스가 HIGH인 시간이 digitalRead가 실행되는 시간입니다.
      3. 예. 위의 테스트 코드 모두 아두이노 스케치 코드입니다.

      삭제