domingo, 13 de mayo de 2018

Principio de multitarea. Desterrando a los delays.


Este artículo tiene como base proponer una metodología para efectuar programas multitarea en microcontroladores usando el compilador CCS PicC.
Todo está en función de un temporizador y la directiva #use timer, no se hace uso de las interrupciones ya que estas estarán reservadas para tareas de mayor prioridad.

La directiva #use timer.

Esta directiva crea un timer tick usando uno de los temporizadores del Pic. El timer tick es inicializado a cero al iniciar el programa. Esta directiva crea una constante con nombre TICKS_PER_SECOND que especifica el número de ticks que ocurren en un segundo.
… mayor información en el help de CCS PicC.
La rutina principal main(), se convertirá en el lanzador de tareas y las tareas serán funciones.
Este modo es ideal para las tareas repetitivas, mientras que las secuenciales requieren algunos “trucos”.
Este método lo vi en uno de los ejemplos que CCS tiene disponible.
#use timer(timer=1,tick=10ms,bits=16,noisr)
Usa el temporizador 1, tick cada 10 milisegundos, tamaño de los ticks 16 bits, no se usa interrupción para actualizar los ticks.

Ejemplo.

Generar el parpadeo de tres leds, el primero con un periodo de 100[ms], el segundo con en periodo de 300[ms] y el tercero con un periodo de 1[s].
Es importante que el tiempo mínimo de repetición de la tarea sea mayor o igual a tick usado en el use timer.

En el archivo main.h

/*****************************************************************************/
#include <16F628A.h>
/*****************************************************************************/
#FUSES NOWDT                    //
#FUSES PUT                      //Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
/*****************************************************************************/
#use delay(internal=4MHz)
/*****************************************************************************/
#use timer(timer=1,tick=100ms,bits=16,noisr)
/*****************************************************************************/

En el archivo main.c.

*****************************************************************************/
#include <main.h>
/*****************************************************************************/
void tarea1()
{
   output_toggle(pin_a0);  //cambia de estado el bit 0 del puerto A
}
/*****************************************************************************/
void tarea2()
{
   output_toggle(pin_a1);  //cambia de estado el bit 1 del puerto A
}
/*****************************************************************************/
void tarea3()
{
   output_toggle(pin_a2);  //cambia de estado el bit 2 del puerto A
}
/*****************************************************************************/
void main()
{
   unsigned int16 tick,tick_tarea1=0,tick_tarea2=0,tick_tarea3=0;
   while(true)                                //bucle infinito
   {
      tick=get_ticks();     //lee el valor actual de los ticks
      if((tick-tick_tarea1)>=TICKS_PER_SECOND/10)//aprox 100ms
      {
         tick_tarea1=tick;//actualiza el los tick de la tarea1
         tarea1();                          //lanza la tarea 1
      }
      if((tick-tick_tarea2)>=TICKS_PER_SECOND/3.3)//aprox 300ms
      {
         tick_tarea2=tick; //actualiza el los tick de la tarea2
         tarea2();                           //lanza la tarea 2
      }
      if((tick-tick_tarea3)>=TICKS_PER_SECOND)       //aprox 1s
      {
         tick_tarea3=tick; //actualiza el los tick de la tarea3
         tarea3();                           //lanza la tarea 3
      }
   }
}
/*****************************************************************************/