[risolto] dubbio su delayMicroseconds

buondì a tutti..
qualcuno sa dirmi se posso usare questa funzione all'interno di una funzione richiamata da interrupt?
so che il delay non funziona in questo caso,ma la delayMicroseconds?

grazie per le risposte :slight_smile:

il codice è:

/* 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);
#if F_CPU >= 20000000L
	// for the 20 MHz clock on rare Arduino boards

	// for a one-microsecond delay, simply wait 2 cycle and return. The overhead
	// of the function call yields a delay of exactly a one microsecond.
	__asm__ __volatile__ (
		"nop" "\n\t"
		"nop"); //just waiting 2 cycle
	if (--us == 0)
		return;

	// the following loop takes a 1/5 of a microsecond (4 cycles)
	// per iteration, so execute it five times for each microsecond of
	// delay requested.
	us = (us<<2) + us; // x5 us

	// account for the time taken in the preceeding commands.
	us -= 2;

#elif F_CPU >= 16000000L
	// 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;
#else
	// for the 8 MHz internal clock on the ATmega168

	// for a one- or two-microsecond delay, simply return.  the overhead of
	// the function calls takes more than two microseconds.  can't just
	// subtract two, since us is unsigned; we'd overflow.
	if (--us == 0)
		return;
	if (--us == 0)
		return;

	// the following loop takes half of a microsecond (4 cycles)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us <<= 1;
    
	// partially compensate for the time taken by the preceeding commands.
	// we can't subtract any more than this or we'd overflow w/ small delays.
	us--;
#endif

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
}

secondo me si.

la delaymillisecond funziona perchè non si basa su interrupt ma su di un ciclo. è comunque un grave errore usare un qualsiasi tipo di delay all'interno di un interrupt, quindi la risposta è NO!

quell'interrupt che mi richiama la funzione è un serialevent..vorrei leggere un pin quando mi viene richiesto,quindi farei un po' di letture distanziate di pochissimo tempo,per evitare disturbi & co..
non mi sembra gravissimo :slight_smile:

grazie a entrambi!!

non mi sembra gravissimo

ed invece lo è, sopratutto considerando che non solo stai bloccando gli interrupt, ma persino la seriale; non so come si comporta sotto, ma se si blocca il circuito HW della seriale in attesa della tua funzione puoi ben capire che la sincronizzazione col pc protrebbe andare a pallino, anche se solo per un carattere.

la soluzione è attivare una flag, e poi da loop verificarla, se attiva la disattivi subito (in modo da ricevere una seconda verifica successiva a quella che sai completando) fai le tue belle misure con tutti i delay che vuoi, e poi via verso altri lidi. :grin:

vedi, io ricevo pacchetti di dimensione fissa..alla fine della ricezione,elaboro ed evenualmente mi blocco per pochi ms..tra un pacchetto e l'altro passano come minimo 100 ms,ma probabilmente 500ms..è per questo motovi che non è grave,a mio parere..in altri contesti t'avrei dato ragione..

Se parliamo di ns o di us è un conto, ma bloccare per 100-500 ms, millisecondi, una ISR non è salutare. Sono troppi.
Puoi rovesciare la cosa, ossia crearti una funzione ISR agganciata ad un interrupt PCINT (cambio di stato) con il quale leggi i segnali sul pin e poi inserisci il dato in un buffer. Dal loop principale elabori i dati ricevuti.

Replichi in buona sostanza ciò che fa la seriale.

no leo, si parla di ms tra una richiesta seriale e l'altra, non tra le letture. Quindi in questo caso direi che l'idea di m_ri può funzionare senza problemi.
Ovvio, che però tutte le dalay e le millis() saranno sfalseranno molto il loro valore, a cui puoi rimediare facendo il conto degli interrupt elaborati nel frattempo, moltiplicare per la durata della funzione (diciamo che del delay basta) e sottrarre il tutto alla delay/millis().

@leo: Tra l'altro questo è uno dei motivi per cui la swRTC sfasa; se si riuscisse ad escludere gli altri interrupt il più possibile, avtresti dei valori molto più reali.

@lesto:
non è possibile isolare una routine di interrupt dalle altre, per il semplice motivo che tutte le ISR sono definite atomiche per default dal compilatore.
Ciò significa che quando viene attivata una routine ISR questa non può essere interrotta da un'altra ISR.
Quindi quando l'ISR della swRTC sta lavorando essa non è interrompibile da nulla ma ciò vale anche nei confronti delle altre ISR relativamente alla swRTC: cioè che essa non può interrompere le altre ISR, perdendo quindi in precisione.

L'unico modo per avere una swRTC molto precisa è modificare il core di Arduino rendendo tutte le altre ISR interrompibili. Il problema però si ritorce poi contro nel senso che dopo sono tutte le altre ISR a diventare inesatte per cui ad esempio una ricezione seriale fa a farsi friggere dato che i tempi saltano e la comunicazione può andar fuori sincronizzazione.

con "escludere" intendo -disattivare- tutti gli interrut possibli e immaginabili, e lasciare solo il minimo indispensabile. per esempio la vecchia SoftwareSerial NON usava interrutp; potresti riesumarla...
certo però che come dici in pratica si sta pensando di riscrivere il core..

@lesto:
Sì ma diventa un cane che si morde la coda perché gli interrupt vengono generati da un sacco di cose differenti.
Ad esempio, la ricezione di un dato tramite I2C attiva un interrupt, non solo la seriale.

@m_ri:
la SoftwareSerial non usava gli interrupt però si bloccava nei cicli di trasmissione e ricezione, dato che monitorava le operazioni tramite codice.