Arduino: delaymicroseconds ()

8

Bagaimana fungsi delayMicroseconds () bekerja. Dari apa yang saya mengerti prescaler dari timer0 diatur ke 64. Untuk clock 16MHz memberikan 4.0uS per hitungan. Saya sedikit bingung dengan matematika untuk sampai ke interval 1uS?

Elang_08
sumber
4
The dokumentasi mengatakan "Fungsi ini bekerja sangat akurat dalam kisaran 3 mikrodetik dan up. Kami tidak dapat menjamin bahwa delayMicroseconds akan melakukan tepat untuk lebih kecil delay-kali." Dokumen untuk micros()mengatakan "Pada papan Arduino 16 MHz (misalnya Duemilanove dan Nano), fungsi ini memiliki resolusi empat mikrodetik (yaitu nilai yang dikembalikan selalu kelipatan empat)."
RedGrittyBrick
Lihat juga electronics.stackexchange.com/q/22584/2191
RedGrittyBrick

Jawaban:

9

Kode sumber untuk fungsi ini didokumentasikan dengan cukup baik dan dapat ditemukan di /usr/share/arduino/hardware/arduino/cores/arduino/wiring.c pada sistem Linux. Sistem Windows akan memiliki jalur yang mirip dengan file wiring.c. Berusahalah untuk menemukan file dan menjelajahinya. Untuk sekarang hanya fokus pada fungsi tunggal ini, tidak bergantung pada fungsi lainnya.

Dengan memeriksa kode Anda akan melihat bahwa ini bukan tentang penghitung waktu, ini semua tentang siklus instruksi. Kode sangat bergantung pada optimisasi kompiler yang persis sama untuk Anda seperti untuk pengembang perpustakaan. Itu asumsi penulis! Jumlah siklus CPU 'dibakar' oleh setiap instruksi didokumentasikan dengan baik dalam dokumen set instruksi Atmel AVR .

Pertama nilai penundaan diperiksa untuk menjadi sama dengan 1, dalam hal ini baru saja kembali dari rutin yang sudah dihabiskan selama mikrodetik waktu CPU.

Kemudian nilai penundaan dikalikan dengan empat ( <<=2). The __asm__-loop kompilasi ke dalam siklus lingkaran 4 CPU. 4 siklus × 4 = 16 siklus. 16MHz / (4 × 4) = 1MHz, yang membutuhkan waktu siklus 1 kita, resolusi yang kita cari.

-2 mikrodetik terakhir (sebelum loop dimulai) lagi koreksi pada compiler memperkenalkan overhead. Memanggil- __asm__kode dari C memerlukan beberapa instruksi tambahan untuk menyimpan register CPU.

Untuk Arduino @ 16MHz yang normal hanya kode berikut yang akan dikompilasi:

/* 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: Kode yang dikompilasi cukup akurat, tetapi perhatikan hal-hal berikut: Pada Arduino ada interupsi waktunya diatur yang sebagian besar tidak menyadari. Ketika interupsi diterima selama eksekusi delayMicroseconds(), waktu delayMicroseconds()akan salah. Anda tentu saja dapat menghentikan interupsi sebelum memanggil delayMicroseconds()dan mengaktifkannya setelah itu, tetapi itu lagi mempengaruhi ketepatan waktu dengan durasi kode yang dikompilasi untuk mengaktifkan / menonaktifkan.

jippie
sumber
Atau jika Anda tidak memiliki Arduino IDE diinstal, file ini tersedia di github.com/arduino/Arduino/blob/master/hardware/arduino/cores/...
microtherion