arduino : delaymicroseconds ()

delayMicroseconds () 함수는 어떻게 작동합니까? 내가 이해 한 바에 따르면 timer0의 프리스케일러는 64로 설정되어 있습니다. 16MHz 클럭의 경우 카운트 당 4.0uS를 제공합니다. 1uS 간격에 도달하기 위해 수학이 약간 혼란 스럽습니까?

댓글

  • 문서 "이 함수는 3 마이크로 초 이상 범위에서 매우 정확하게 작동합니다. delayMicroseconds가 더 짧은 지연 시간에 대해 정확하게 작동한다고 보장 할 수 없습니다. " micros() 문서에 " 16MHz Arduino 보드 (예 : Duemilanove 및 Nano)에서이 함수는 4 마이크로 초의 해상도를 갖습니다 (즉, 반환 된 값은 항상 4의 배수입니다). "
  • electronics.stackexchange.com/q/22584/2191
  • 참조

답변

이 함수의 소스 코드는 상당히 잘 문서화되어 있으며 / usr / share / arduino / hardware에서 찾을 수 있습니다. Linux 시스템의 경우 /arduino/cores/arduino/wiring.c. Windows 시스템은 wire.c 파일과 유사한 경로를 갖습니다. 파일을 찾고 찾아 보는 노력을 기울이십시오. 지금은이 단일 함수에 초점을 맞추고 “다른 기능에 의존하지 않습니다.

코드를 검사하면 타이머에 관한 것이 아니라 명령주기에 관한 것임을 알 수 있습니다. 코드는 라이브러리 개발자와 똑같은 컴파일러 최적화에 크게 의존합니다. 저자의 가정! 각 명령어에 의해 “소각 된”CPU 사이클 수는 Atmel AVR 명령어 세트 문서 에 잘 설명되어 있습니다.

먼저 지연 값은 다음과 같습니다. 1 마이크로 초의 CPU 시간 동안 이미 소비 된 루틴에서 돌아 오는 경우 1과 같은지 확인합니다.

그런 다음 지연 값에 4를 곱합니다 (<<=2). __asm__-루프는 4 CPU 사이클 루프로 컴파일됩니다. 4주기 × 4 = 16주기. 16MHz / (4×4) = 1MHz, 1 us 사이클 시간, 우리가 추구하는 분해능

마지막 -2 마이크로 초 (루프가 시작되기 전)는 다시 컴파일러의 수정입니다. 도입 된 오버 헤드. C에서 __asm__ 코드를 호출하려면 CPU 레지스터를 저장하기위한 추가 지침이 필요합니다.

일반 Arduino @ 16MHz의 경우 다음 코드 만 컴파일됩니다.

/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ void delayMicroseconds(unsigned int us) { // calling avrlib"s delay_us() function with low values (e.g. 1 or // 2 microseconds) gives delays longer than desired. //delay_us(us); // for the 16 MHz clock on most Arduino boards // for a one-microsecond delay, simply return. the overhead // of the function call yields a delay of approximately 1 1/8 us. if (--us == 0) return; // the following loop takes a quarter of a microsecond (4 cycles) // per iteration, so execute it four times for each microsecond of // delay requested. us <<= 2; // account for the time taken in the preceeding commands. us -= 2; // busy wait __asm__ __volatile__ ( "1: sbiw %0,1" "\n\t" // 2 cycles "brne 1b" : "=w" (us) : "0" (us) // 2 cycles ); } 

BTW : 컴파일 된 코드는 매우 정확하지만 다음 사항에 유의하십시오. Arduino에는 대부분이 인식하지 못하는 시간 제한 인터럽트가 구성되어 있습니다. delayMicroseconds() 실행 중에 인터럽트가 수신되면 delayMicroseconds() 타이밍이 잘못됩니다. 물론 delayMicroseconds()를 호출하기 전에 인터럽트를 중지하고 나중에 활성화 할 수 있지만 이는 활성화 / 비활성화를 위해 컴파일 된 코드 기간에 따라 타이밍 정확도에 다시 영향을 미칩니다.

의견

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다