Hogyan működik a delayMicroseconds () függvény. Amit megértettem, az időzítő előmérője 64-re van állítva. Egy 16 MHz-es órajelenként 4,0 uS-ot ad. Kicsit zavart vagyok a matematikában, hogy 1uS intervallumra jussak?
Megjegyzések
Válasz
A függvény forráskódja meglehetősen jól dokumentált és megtalálható a / usr / share / arduino / hardware könyvtárban /arduino/cores/arduino/wiring.c Linux rendszereken. A Windows rendszereknek hasonló az elérési útja, mint a wiring.c fájlnak. Tegyen erőfeszítéseket a fájl megkeresésére és böngészésére. Most csak erre az egyetlen funkcióra összpontosítson, és nem támaszkodik más funkciókra.
A kód megvizsgálásával észreveheti, hogy nem az időzítőkről, hanem az utasítások ciklusairól szól. A kód nagyban támaszkodik arra, hogy a fordító optimalizálása pontosan ugyanaz legyen az Ön számára, mint a könyvtár fejlesztőjének. Ez a szerző feltételezése! Az egyes utasítások által “elégetett” CPU-ciklusok száma jól dokumentálva van az Atmel AVR utasításkészlet dokumentumban .
Először a késleltetés értéke ellenőrzik, hogy egyenlő-e 1-vel, ebben az esetben csak visszatérve a már elköltött rutinból a mikroprocesszor egy mikroszekunduma alatt.
Ezután a késleltetési értéket megszorozzuk négyzel (<<=2
). A __asm__
-loop 4 CPU ciklusba fordít. 4 ciklus × 4 = 16 ciklus. 16MHz / (4 × 4) = 1MHz, ami 1 ciklus időt vesz igénybe, az a felbontás, amelyet követünk.
Az utolsó -2 mikroszekundum (mielőtt a hurok elindulna) ismét korrekció a fordítóban bevezetett rezsi. A __asm__
-kód C-től történő meghívásához további utasításokra van szükség a CPU-regiszterek mentéséhez.
Normál Arduino @ 16MHz esetén csak a következő kód kerül összeállításra:
/* 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: A lefordított kód meglehetősen pontos, de vegye figyelembe a következőket: Az Arduino-n vannak olyan időzített megszakítások, amelyek nincsenek tisztában. Amikor a delayMicroseconds()
végrehajtása közben megszakítás érkezik, a delayMicroseconds()
időzítése hibás lesz. Természetesen leállíthatja a megszakításokat, mielőtt felhívja a delayMicroseconds()
t, és utána engedélyezheti őket, de ez ismét befolyásolja az időzítés pontosságát az engedélyezés / letiltás fordított kódjának időtartamával.
Megjegyzések
- Vagy ha még nincs telepítve az Arduino IDE, ez a fájl a github.com/arduino címen érhető el. / Arduino / blob / master / hardware / arduino / core / …
- Ez ' s ide költözött: github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/…
micros()
dokumentumai " 16 MHz-es Arduino táblákon (pl. Duemilanove és Nano) ennek a funkciónak négy mikroszekundum a felbontása (vagyis a visszaadott érték mindig négyes többszöröse). "