Cum se face întârzierea microsecundă în AVR (ATmega8) cu temporizator? (Programare, Timer, Întârziere, Avr, Avr Gcc)

Mahdi a intrebat.
a intrebat.

Vreau să fac o întârziere variabilă în ATmega8. Dar în funcția delay_us(), pot pune doar o valoare constantă. Cred că pot face o microsecundă de întârziere variabilă cu un timer, dar nu știu cum să lucrez cu acest lucru.

Vă rog să mă ajutați.

Comentarii

  • Ați putea împărtăși ce ați făcut deja? –  > Por dunajski.
  • când scriu delay_us(i) și i este o variabilă, codevision errored. –  > Por Mahdi.
  • Vă rugăm să furnizați un cod. Nu puteți seta o variabilă la delay_us deoarece delay_us(x) este un macro care inserează un cod suplimentar care generează o întârziere de x µ-secunde. Atunci când aveți nevoie de o întârziere variabilă, trebuie să utilizați un temporizator. –  > Por Kampi.
1 răspunsuri
Edgar Bonet

Poți folosi o buclă de întârziere: întârzii o microsecundă la fiecare iterație și faci atâtea iterații câte microsecunde trebuie să arzi:

void delay_us(unsigned long us)
{
    while (us--) _delay_us(1);
}

Există, totuși, câteva probleme cu această abordare:

  • este nevoie de timp pentru a gestiona iterațiile (descreșterea contorului, compararea la zero, ramura condiționată…), astfel încât întârzierea în cadrul buclei ar trebui să fie semnificativ mai mică decât 1 µs
  • este nevoie de timp pentru a apela funcția și a reveni de la ea, iar acest timp ar trebui să fie scăzut din numărul de iterații, dar, deoarece acest timp poate să nu fie un număr complet de microsecunde, va trebui să adăugați o mică întârziere pentru a ajunge la următoarea microsecundă completă.
  • în cazul în care compilatorul introduce funcția în linie, totul va fi oprit.

Încercarea de a rezolva aceste probleme duce la ceva de genul următor:

// Only valid with a 16 MHz clock.
void __attribute__((noinline)) delay_us(unsigned long us)
{
    if (us < 2) return;
    us -= 2;
    _delay_us(0.4375);
    while (us--) _delay_us(0.3125);
}

Pentru o versiune mai completă care poate gestiona diferite frecvențe de ceas, consultați delayMicroseconds() funcția din Arduino AVRcore. Observați că funcția este precisă doar pentru câteva frecvențe discrete. Observați, de asemenea, că bucla de întârziere este realizată în asamblare inline, pentru a fi independentă de optimizările compilatorului.