인터럽트 루틴 내에서 millis () 및 micros () 사용


13

에 대한 설명서 attachInterrupt()는 다음과 같습니다.

... millis()카운트 할 인터럽트에 의존하므로 ISR 내부에서는 절대 증가하지 않습니다. delay()인터럽트가 작동해야 하므로 ISR 내부에서 호출하면 작동하지 않습니다. micros()처음에는 작동하지만 1-2ms 후에 비정상적으로 작동하기 시작합니다. ...

정밀도는 물론 micros()다른 점과 어떻게 다릅니 millis()까? 위의 경고 micros()는 인터럽트 루틴 내부에서 사용 하는 것이 항상 나쁜 생각이라는 것을 의미합니까?

컨텍스트- 낮은 펄스 점유율측정 하려고 하므로 입력 신호가 변경되고 현재 시간을 기록 할 때 루틴을 트리거해야합니다.

답변:


16

다른 답변은 매우 좋지만 micros()작동 방식 에 대해 자세히 설명하고 싶습니다 . 그것은 항상 현재의 하드웨어 타이머 (아마도 읽어 TCNT0지속적으로 하드웨어에 의해 업데이트되는) (사실, 때문에 64의 프리스케일러의 모든 4 μS). 그런 다음 타이머 0 오버플로 카운트를 추가하고 타이머 오버플로 인터럽트 (256을 곱한 값)로 업데이트됩니다.

따라서 ISR 내부에서도 micros()업데이트에 의존 할 수 있습니다 . 그러나 너무 오래 기다리면 오버플로 업데이트를 놓치면 반환 결과가 내려갑니다 (예 : 253, 254, 255, 0, 1, 2, 3 등)

이것은 micros()다른 프로세서에 대한 정의를 제거하기 위해 약간 단순화되었습니다.

unsigned long micros() {
    unsigned long m;
    uint8_t oldSREG = SREG, t;
    cli();
    m = timer0_overflow_count;
    t = TCNT0;
    if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++;
    SREG = oldSREG;
    return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

위의 코드는 오버플로 (TOV0 비트 검사)를 허용하므로 인터럽트가 해제되어 있지만 한 번만 오버플로를 처리 할 수 ​​있습니다. 두 개의 오버플로를 처리 할 준비가 없습니다.


TLDR;

  • ISR 내부에서 지연하지 마십시오
  • 당신이 그 (것)들을해야하는 경우에, 당신은 시간을 할 수 micros()있지만 아닙니다 millis(). 또한 delayMicroseconds()가능성이있다.
  • 500 µs 이상 지연하지 마십시오. 타이머 오버플로가 빠질 수 있습니다.
  • 약간의 지연이라도 수신 직렬 데이터를 놓칠 수 있습니다 (115200 보드에서 87µs마다 새 문자가 표시됨).

micros ()에서 사용되는 아래 설명을 이해할 수 없습니다. 좀 더 자세히 설명해 주시겠습니까? ISR이 작성되었으므로 ISR이 입력 되 자마자 TOV0 플래그가 지워 지므로 아래 조건이 충족되지 않을 수 있습니다. if ((TIFR0 & _BV (TOV0)) && (t <255)) m ++;
Rajesh

micros()ISR이 아닙니다. 정상적인 기능입니다. TOV0 플래그를 사용하면 타이머 오버 플로우가 발생했는지 (아직 처리되지 않은) 하드웨어를 테스트 할 수 있습니다.
Nick Gammon

테스트는 인터럽트를 끈 상태에서 수행되므로 테스트 중에 플래그가 변경되지 않습니다.
Nick Gammon

따라서 micros () 함수 내부의 cli () 뒤에 오버플로가 발생하면 검사해야한다고 말합니까? 말 되네. 그렇지 않으면 마이크로는 함수가 아니지만 TIMER0_OVF_vect ISR은 TIFR0에서 TOV0을 지 웁니다.
Rajesh

또한 TCNT0을 255와 비교하여 255보다 작은 이유는 무엇입니까? TCNT0이 255에 도달하면 cli () 후 어떻게됩니까?
Rajesh

8

인터럽트 루틴 을 사용 하거나 사용하는 것은 잘못 이 아닙니다 .millis()micros()

이다 잘못을 사용하는 것은 잘못.

여기서 가장 중요한 것은 인터럽트 루틴이 진행되는 동안 "시계가 똑딱 거리지 않는다"는 것입니다. millis()그리고 micros()변경되지 않습니다 (물론, micros()처음에는 밀리 초 틱이 필요한 마술 밀리 초 지점을 지나면 모두 분리됩니다.)

따라서 ISR 내에서 현재 시간을 요청 millis()하거나 micros()확인할 수는 있지만 그 시간이 변경 될 것으로 기대하지는 않습니다.

당신이 제공 한 견적에 대해 경고하고있는 시간의 변화가 부족하다는 것입니다. 얼마나 많은 시간이 지 났는지 알기 위해 변화에 delay()의존합니다 millis(). 그것이 변하지 않기 때문에 delay()결코 끝날 수 없습니다.

그래서 본질적으로 millis()그리고 micros()당신에게 시간이 말해 줄 것이다 당신의 ISR이 호출되지 않았다 당신의 ISR에 당신이 그들을 사용하는 경우에 상관없이합니다.


3
아니요, micros()업데이트합니다. 항상 하드웨어 타이머 레지스터를 읽습니다.
Nick Gammon

4

인용 된 문구는 없습니다 그것은 단지 사물이 작동하는 방법에 대한 성명, 경고.

올바르게 작성된 인터럽트 루틴 을 사용 millis()하거나 사용하는 데 본질적으로 아무런 문제가 없습니다 micros().

반면에, 잘못 작성된 인터럽트 루틴 내에서 아무것도하지 않는 것은 정의상 잘못입니다.

작업을 수행하는 데 몇 마이크로 초 이상 걸리는 인터럽트 루틴은 잘못 작성되었습니다.

한마디로 : 제대로 작성된 인터럽트 루틴은 발생하지 않습니다 또는에서 발생할 문제 millis()micros().

편집 : " Arduino 마이크로 기능 검사 "웹 페이지에 설명 된 "micros ()가 비정상적으로 작동하는 이유"와 관련 micros()하여 일반 Uno의 코드는 기능적으로

unsigned long micros() {
  return((timer0_overflow_count << 8) + TCNT0)*(64/16);
}

timer0_overflow_counttimer-0 카운트 레지스터 에서 3 개의 가장 낮은 바이트 와 1 바이트 로 구성된 4 바이트의 부호없는 long을 반환합니다 .

timer0_overflow_count바이 밀리 초마다 한번씩 증가 TIMER0_OVF_vect인터럽트 핸들러로 설명 아두 이노 밀리 기능 검사 웹 페이지.

인터럽트 핸들러가 시작되기 전에 AVR 하드웨어는 인터럽트를 비활성화합니다. (예를 들어, 인터럽트 핸들러가 여전히 인터럽트가 비활성화 된 상태에서 5 밀리 초 동안 실행 된 경우, 최소 4 개의 타이머 0 오버 플로우가 누락됩니다. [Arduino 시스템에서 C 코드로 작성된 인터럽트는 재진입 할 ​​수 없지만 (동일한 핸들러 내에서 여러 개의 겹치는 실행을 올바르게 처리 할 수는 없지만) 시간이 걸리는 프로세스를 시작하기 전에 인터럽트를 재 활성화 할 수있는 재진입 자 어셈블리 언어 핸들러를 작성할 수 있습니다.]

다시 말해 타이머 오버플로는 "스택"되지 않습니다. 이전 오버 플로우의 인터럽트가 처리되기 전에 오버 플로우가 발생할 때마다 millis()카운터는 밀리 초를 잃어 버리고 timer0_overflow_count차례로 불일치 micros()도 밀리 초만큼 잘못됩니다.

"너무 긴 시간 동안 타이머 인터럽트 차단을 방지하기 위해"인터럽트 처리의 상한으로 "500 μs 미만"을 고려하면 1024 μs 미만 (예 : 1020 μs)까지 올라갈 수 있습니다 millis(). 시각. 그러나 나는 5μs 이상을 sluggard로, 10μs 이상을 느리게, 20μs를 달팽이 모양으로 취하는 인터럽트 핸들러를 생각합니다.


"어떻게 작동 하는가", 특히 micros()"불규칙하게 행동하기 시작하는 이유 " 에 대해 자세히 설명해 주 시겠습니까? "적절하게 작성된 인터럽트 루틴"은 무엇을 의미합니까? "500us보다 짧은"(너무 긴 시간 동안 타이머 인터럽트 차단을 방지하기 위해), "통신에 휘발성 변수 사용"및 "라이브러리 코드를 호출하지 않음"을 의미한다고 가정합니다.
Petr Pudlák

@ PetrPudlák, 편집 참조
James Waldby-jwpat7 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.