arduino: delaymicroseconds () (Português)

Como funciona a função delayMicroseconds (). Pelo que entendi, o prescaler do timer0 está definido para 64. Para um clock de 16 MHz dá 4.0uS por contagem. Estou um pouco confuso com a matemática para chegar ao intervalo 1uS?

Comentários

  • O a documentação diz " Esta função funciona com muita precisão no intervalo de 3 microssegundos ou mais. Não podemos garantir que delayMicroseconds serão executados precisamente para tempos de atraso menores. " A documentação para micros() diz " Em placas Arduino de 16 MHz (por exemplo, Duemilanove e Nano), esta função tem uma resolução de quatro microssegundos (ou seja, o valor retornado é sempre um múltiplo de quatro). "
  • Veja também electronics.stackexchange.com/q/22584/2191

Resposta

O código-fonte para esta função está bastante bem documentado e pode ser encontrado em / usr / share / arduino / hardware /arduino/cores/arduino/wiring.c em sistemas Linux. Os sistemas Windows terão um caminho semelhante para o arquivo wiring.c. Faça o esforço de encontrar o arquivo e navegar por ele. Por enquanto, concentre-se apenas nesta única função, ela não depende de nenhuma outra função.

Ao inspecionar o código, você perceberá que não se trata de temporizadores, mas de ciclos de instrução. O código depende muito da otimização do compilador, sendo exatamente o mesmo para você e para o desenvolvedor da biblioteca. Essa é uma suposição do autor! O número de ciclos de CPU “queimados” por cada instrução está bem documentado no documento de conjunto de instruções Atmel AVR .

Primeiro, o valor de atraso é verificado para ser igual a 1, nesse caso apenas retornando da rotina já gasto em um microssegundo de tempo de CPU.

Então o valor de atraso é multiplicado por quatro (<<=2). O __asm__ -loop compila em um loop de 4 ciclos de CPU. 4 ciclos × 4 = 16 ciclos. 16 MHz / (4 × 4) = 1 MHz, o que leva 1 us de tempo de ciclo, a resolução que buscamos.

Os últimos -2 microssegundos (antes do loop ser iniciado) são novamente uma correção no compilador introduzido sobrecarga. Chamar __asm__ -code do C requer algumas instruções extras para salvar os registros da CPU.

Para um Arduino normal a 16 MHz, apenas o seguinte código será compilado:

/* 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: O código compilado é bastante preciso, mas esteja ciente do seguinte: No Arduino, há interrupções temporizadas configuradas que a maioria desconhece. Quando uma interrupção é recebida durante a execução de delayMicroseconds(), o tempo de delayMicroseconds() estará errado. É claro que você pode parar as interrupções antes de chamar delayMicroseconds() e habilitá-las depois, mas isso novamente afeta a precisão do tempo pela duração do código compilado para habilitar / desabilitar.

Comentários

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *