arduino: delaymicroseconds () (Dansk)

Hvordan fungerer funktionen delayMicroseconds (). Fra hvad jeg forstod, er prescaler af timer0 indstillet til 64. For et 16MHz giver uret 4,0 us pr. Optælling. Jeg er lidt forvirret i matematikken for at komme til 1uS-intervallet?

Kommentarer

  • dokumentation siger " Denne funktion fungerer meget præcist i intervallet 3 mikrosekunder og op. Vi kan ikke forsikre, at delayMicroseconds fungerer præcist for mindre forsinkelsestider. " Dokumenterne for micros() siger " På 16 MHz Arduino-kort (f.eks. Duemilanove og Nano) har denne funktion en opløsning på fire mikrosekunder (dvs. den returnerede værdi er altid et multiplum af fire). "
  • Se også electronics.stackexchange.com/q/22584/2191

Svar

Kildekoden til denne funktion er ret veldokumenteret og kan findes i / usr / share / arduino / hardware /arduino/cores/arduino/wiring.c på Linux-systemer. Windows-systemer vil have en lignende sti til filen wiring.c. Brug en indsats for at finde filen og gennemse den. For nu er det bare at fokusere på denne enkelt funktion, den stoler ikke på nogen anden funktion.

Ved at inspicere koden vil du bemærke, at det ikke handler om timere, det handler om instruktionscyklusser. Koden er stærkt afhængig af, at compileroptimering er nøjagtig den samme for dig som for udvikleren af biblioteket. Det er en antagelse fra forfatteren! Antallet af CPU-cyklusser “brændt” af hver instruktion er veldokumenteret i Atmel AVR instruktions sæt dokument .

Først er forsinkelsesværdien kontrolleret for at være lig med 1, i så fald bare at vende tilbage fra den rutine, der allerede er brugt over et mikrosekund af CPU-tid.

Så ganges forsinkelsesværdien med fire (<<=2). __asm__ -loop kompileres til en 4 CPU-cyklusløkke. 4 cyklusser × 4 = 16 cyklusser. 16MHz / (4 × 4) = 1MHz, hvilket tager 1 us cyklustid, den opløsning, vi er efter.

De sidste -2 mikrosekunder (før sløjfen startes) er igen en korrektion på compileren introduceret overhead. Opkald til __asm__ -kode fra C kræver nogle ekstra instruktioner for at gemme CPU-registre.

For en normal Arduino @ 16MHz kompileres kun følgende kode:

/* 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: Den kompilerede kode er ret nøjagtig, men vær opmærksom på følgende: På Arduino er der konfigureret tidsintervaller, som de fleste ikke er opmærksomme på. Når der modtages en afbrydelse under udførelsen af delayMicroseconds(), vil timingen af delayMicroseconds() være forkert. Du kan selvfølgelig stoppe afbrydelser, før du ringer til delayMicroseconds() og aktivere dem bagefter, men det påvirker igen timingnøjagtigheden af varigheden af den kompilerede kode til aktivering / deaktivering.

Kommentarer

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *