arduino: delaymicroseconds () (Română)

Cum funcționează funcția delayMicroseconds (). Din ceea ce am înțeles, prescalerul timer0 este setat la 64. Pentru un ceas de 16 MHz dă 4.0uS pe număr. Sunt un pic confuz cu privire la matematică pentru a ajunge la intervalul 1uS?

Comentarii

  • documentația spune " Această funcție funcționează foarte precis în intervalul de 3 microsecunde sau mai mult. Nu putem asigura că delayMicroseconds va funcționa cu precizie pentru timpi de întârziere mai mici. " Documentele pentru micros() spune " Pe plăcile Arduino de 16 MHz (de ex. Duemilanove și Nano), această funcție are o rezoluție de patru microsecunde (adică valoarea returnată este întotdeauna un multiplu de patru). "
  • Consultați și electronics.stackexchange.com/q/22584/2191

Răspuns

Codul sursă pentru această funcție este destul de bine documentat și poate fi găsit în / usr / share / arduino / hardware /arduino/cores/arduino/wiring.c pe sistemele Linux. Sistemele Windows vor avea o cale similară cu fișierul wiring.c. Faceți efortul de a găsi fișierul și de a-l răsfoi. Deocamdată concentrați-vă doar pe această funcție unică, nu se bazează pe alte funcții.

Inspectând codul veți observa că nu este vorba de cronometre, ci de cicluri de instrucțiuni. Codul se bazează în mare măsură pe optimizarea compilatorului, fiind exact același pentru dvs. ca pentru dezvoltatorul bibliotecii. Aceasta este o presupunere a autorului! Numărul de cicluri CPU „arse” de fiecare instrucțiune este bine documentat în documentul setului de instrucțiuni Atmel AVR .

verificat pentru a fi egal cu 1, în acest caz tocmai reveniți din rutina deja petrecută peste o microsecundă de timp CPU.

Apoi valoarea întârzierii este înmulțită cu patru (<<=2). Bucla __asm__ se compilează într-o buclă de ciclu de 4 CPU. 4 cicluri × 4 = 16 cicluri. 16MHz / (4 × 4) = 1MHz, care necesită 1 ciclu de timp, rezoluția după care urmărim.

Ultimele -2 microsecunde (înainte ca bucla să fie lansată) este din nou o corecție pe compilator introdus deasupra capului. Apelarea codului __asm__ de la C necesită câteva instrucțiuni suplimentare pentru a salva registrele procesorului.

Pentru un Arduino normal @ 16MHz va fi compilat doar următorul cod:

/* 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: Codul compilat este destul de precis, dar rețineți următoarele: pe Arduino există întreruperi temporizate configurate de care majoritatea nu știu. Când se primește o întrerupere în timpul executării delayMicroseconds(), calendarul delayMicroseconds() va fi greșit. Bineînțeles, puteți opri întreruperile înainte de a apela delayMicroseconds() și le puteți activa ulterior, dar acest lucru are din nou impact asupra preciziei de sincronizare până la durata codului compilat pentru activare / dezactivare.

Comentarii

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *