Cómo implementar funciones de retardo en Keil ARM MDK [cerrado]

2

¿Cómo implementar la función de demora en Keil ARM MDK que espera un tiempo determinado en microsegundos que puede recompilarse a cualquier velocidad de reloj razonable definida en la configuración del proyecto de Keil? Y todo esto sin utilizar temporizadores.

    
pregunta x4mer

4 respuestas

5

El mejor método, en mi humilde opinión, es tener un temporizador de hardware que nunca se escribe, sino que simplemente se ejecuta de forma gratuita. Esto le permitirá a uno emular fácilmente un temporizador de sondeo arbitrario para duraciones de hasta la mitad de la longitud del temporizador de hardware. Para "iniciar" un temporizador, simplemente calcule el valor del temporizador de hardware cuando debería expirar. Para ver si un temporizador ha expirado aún, reste el tiempo de vencimiento esperado de la hora actual (con respecto a ambas cantidades como sin firmar), y vea si el resultado (sin firmar) excede la mitad del valor máximo del temporizador. Si es así, el temporizador no ha expirado.

Alternativamente, si uno quiere un temporizador para medir el tiempo desde que ocurrió un evento determinado, simplemente puede bloquear el valor del temporizador cuando ocurrió el evento, y luego calcular la diferencia entre el valor bloqueado y la hora actual.

    
respondido por el supercat
2

Tendrá que determinar la longitud de un NOP, y luego usar #Define lo hace para que, según la velocidad del reloj, inserte el número correcto.

Específicamente, desea saber el número exacto de ciclos de reloj necesarios para que se complete 1 bucle del estilo:

for(long i=0;i<NUMBER_OF_LOOPS_REQUIRED;i++)
{
  __NOP();
}

Al hacer que #define para la cantidad de bucles requeridos se reconfigure para que sea automático en función del retraso solicitado y la velocidad de reloj en la que se está ejecutando actualmente. Todo esto se puede envolver en una macro.

    
respondido por el Kortuk
2
#if _Main_Crystal == 25000000
   #define LOOP_DELAY 400
#elif  _Main_Crystal == 16000000
   #define LOOP_DELAY 256
#else
   #error microsecond delay must be adjusted!
#endif
void usDelay( void )
{
   for (int i = 0; i < LOOP_DELAY; i++)
   {
      SERVICE_WATCH_DOG();
   }
}

donde SERVICE_WATCH_DOG() es una macro para dar servicio al temporizador del perro guardián. Esto también se puede reemplazar con un NOP .

Use una función de prueba para averiguar cuáles deben ser sus constantes LOOP_DELAY para cada frecuencia de reloj:

void TestDelay( void )
{
   SetIOPin();    // Use a scope to start measuring elapsed time here.
   usDelay();
   ResetIOPin();  // use a scope to end measuring elapsed time here.
}
    
respondido por el semaj
0

Se prefiere una referencia de temporizador de hardware porque un buen optimizador podría eliminar el bucle por completo o alterarlo según la configuración. El otro problema con los bucles de temporización que no se menciona aquí es que si se produce una interrupción durante su bucle de temporización, podría llevar mucho más tiempo. Las interrupciones deben ser cortas de todos modos, pero no todos los sistemas siguen ese mantra.

    
respondido por el strawbot

Lea otras preguntas en las etiquetas