Ejecutando código a diferentes velocidades, usando un temporizador y sin RAM extra

1

Me preguntaba, ¿funcionará esto de verdad? (cuando se configura el temporizador / prescaler) Ahorra RAM al no usar variables adicionales. ¿Son las mejores formas de hacer esto?

// Microchip PIC10F222

while (1) {  //main loop
   while ((TMR0 ^ TMR0-1)& 4) {  // execute @ 1/4 speed of TMR0 (whenever TMR0 Bit 3 has just toggled)
   // high speed stuff
   }

   while ((TMR0 ^ TMR0-1)& 128) {   // execute @ 1/128 speed of TMR0
   // low speed stuff (toggle blinking led's) 
   }
}

Siguiente idea:

No me gusta la idea de perder tiempo en el procesador, o de depender de la sincronización exacta

No estoy seguro sobre el TMR0-2. Supongo que si TMR0 = 0 TMR0-2 será 254.

// Microchip PIC10F222

While(1) { //main loop
    // Full speed 
    if (TMR0&1) {  //skip, eccept for TMR0 odd numbers.
       // 1/1 timer speed. (Not nececairily used)
       // this code may run in one pass with either one of the loops below. 
       if ((TMR0 ^ TMR0-2)& 64) {    
          // 1/32 timer speed,(state machines, one step each pass.)   
          // do not exceed TMR0 period
          }
       if ((TMR0==255) {     
          // 1/128 timer speed. (toggle blinking led's, wachdogg)
          // do not exceed TMR0 period
          }
    TMR0++; //TMR0 will be even, preventing passing trough this loop
            //until the timer increments itself, 
            //(Doubeling timer speed in the process)
    }
}
    
pregunta D.J.W.

2 respuestas

1

El PIC10F222 no tiene interrupciones, solo 2 niveles de pila de llamadas y muy poca memoria. Las técnicas que son apropiadas para chips más potentes pueden ser ineficientes o no funcionar en absoluto. Para evitar ciclos de "desperdicio" mientras espera un poco de alternancia, puede hacer un código en línea para hacer otras cosas mientras espera (por ejemplo, hacer cosas de alta velocidad mientras espera para activar el bit de baja velocidad).

Para detectar cuándo cambia un bit, debe esperar hasta que el bit esté en un estado, luego espere de nuevo para que cambie a otro estado. El siguiente código ejecuta material de alta velocidad cada vez que el bit 1 de TMR0 cambia de bajo a alto, y ejecuta material de baja velocidad cada vez que el bit 6 cambia de bajo a alto. No se utiliza RAM.

Si todas tus 'cosas' se completan dentro del intervalo de tiempo de alta velocidad actual, entonces estará perfectamente sincronizado con el temporizador, sin ciclos desperdiciados. Si toma demasiado tiempo y se pierde el cambio de bit, entonces tendrá que esperar al siguiente. Si algunas "cosas" tardan demasiado tiempo, entonces puede dividirlas en dos o más partes y hacer cada parte en un intervalo de tiempo diferente.

// Microchip PIC10F222
#include <pic.h>

main ()
{
   while (1) {  
      while (TMR0 & 64) {   // wait until bit 6 goes low. 
         while (TMR0 & 2) { // wait until bit 1 goes low 
         }
         while (!(TMR0 & 2)){ // wait until bit 1 goes high
         }
         // while waiting for bit 6, do high speed stuff
      }
      while (!(TMR0 & 64)){ // wait until bit 6 goes high
         while (TMR0 & 2) { // wait until bit 1 goes low
         }
         while (!(TMR0 & 2)){ // wait until bit 1 goes high
         }
         // while waiting for bit 6, do high speed stuff again
      }
      // do low speed stuff
   }
}
    
respondido por el Bruce Abbott
0

Como dijo Brian, si tus cosas de alta velocidad terminaron antes de que se incremente el temporizador, se ejecutará varias veces (si eso es lo que quieres, entonces no estoy seguro de qué tipo de procesamiento estás haciendo), y si algo tarda demasiado tiempo, te perderás futuros eventos. Además, su procesador seguirá gritando a través de este bucle 100% del tiempo, lo que no es bueno para el consumo de energía. Si planeas tener otro código en tu bucle, eso también podría hacer que pierdas eventos.

Según tengo entendido, una forma mucho mejor de hacer esto es implementar programación dirigida por eventos . Haga que una variable almacene las tareas pendientes como bits, y su bucle principal los atenderá tan pronto como se eleven los bits. Su temporizador puede establecer esos bits en una interrupción, o si no le gustan las interrupciones, el bucle principal puede sondear el temporizador en cada rotación de la siguiente manera:

while(1)
{
    if (sys_event & 0x01)
    {
        // High speed task, executed with a higher priority
    }
    else if (sys_event & 0x02)
    {
        // Low speed task, executed with a lower priority
    }
    // More events, in order of priority

    if (TMR0 >= 0x04)
    {
        sys_event |= 0x01; // Raise high-speed flag
        TMR0 = 0;          // Reset timer

        if(--slow_wait == 0)   // Counter for slow event
        {
            sys_event |= 0x02; // Raise low-speed flag
            slow_wait = 32;    // Reset slow count
        }
    }
}

Supongo que esa es una variable adicional para el contador slow_wait , pero la lección aquí es que encuestar algo asíncrono como el temporizador puede ser una mala idea, ya que es posible que obtengas múltiples desencadenantes o eventos perdidos. Una vez más, esta implementación funciona incluso mejor si TMR0 desencadena una interrupción. Si el PIC que está utilizando es compatible con los modos de bajo consumo o modo de espera (estoy acostumbrado al MSP430, perdóneme si me estoy yendo mal con esto), puede hacer que el procesador se apague para esperar algún evento. para dar servicio, y simplemente haga que la interrupción se active cuando haya algo que hacer.

Una cosa que es importante para esta implementación (y cualquier sistema multitarea no preventivo) es que las rutinas del servicio de eventos deben ser rápidas. Si tiene que suceder mucho o continuamente, entonces vuelva a activar el evento con frecuencia (incluso cada vez) y déle una prioridad baja (de esa manera siempre sucede si no hay nada más que hacer, pero otros eventos pueden ocurrir con poca latencia). Sin embargo, incluso entonces, haga que el código se devuelva rápidamente .

Espero que eso ayude, mis disculpas si realmente no entendí la esencia de tu pregunta.

    
respondido por el krs013

Lea otras preguntas en las etiquetas