Hola a todos. Llevo poco más de 1 año siendo usuario de vuestra magnífica comunidad, pero nunca me había decidido a añadir algo interesante o no (puesto que hay profesionales aquí que a mi lado yo parezco una hojita en pleno suelo).
Pero hoy os voy a traer algo interesante. Antes de nada, se trata de programación en C.
¿De qué se tratará? Pues de la programación mediante threads o hilos de programación en paralelo.
Todos los que alguna vez hayamos dado diseño digital sabemos que eso es imposible, una unidad aritmética sólo podría hacer un cálculo cada vez, pero es posible "entrelazar" procesos para que, de forma más o menos compleja, puedan hacer dos tareas en paralelo, e incluso establecer una serie de preferencias entre hilos para que se ejecuten algunos hilos más frecuentemente que otros (un símil a como se hacía con los procesadores mononúcleo en ordenadores multitarea)
Rebuscando cosas interesantes por internet, encontré esto:
http://www.romanblack.com/PICthread.htmUn tipo que pretendía lo que os comento, pero en inglés, y como aquí la lengua anglosajona no la practicamos, os traduzco por encima más o menos lo que comenta.
Resulta que si pretendemos hacer paralelismos en pic, pero poseemos funciones que consumen gran cantidad de tiempo y otras que no consumen tanto pero que son más importantes o más necesarias que las primeras, pues habrá que inventar alguna manera posible de poder intercalar ambas de forma lo más sencilla para el programador, que no implique ni un gasto de memoria excesivo, ni tampoco un tiempo de selección de hilo y/o proceso.
Pues al señor roman black este se le ocurrió que, mediante una tontería muy grande de #defines, podríamos.
Se inserta el siguiente código al principio de nuestro pic y luego pongo un ejemplo de cómo funciona:
unsigned char secuencia[NUMERO_DE_HILOS];
unsigned char secuencia_hilo;
unsigned char temporizador_secuencia_hilo;
#define COMIENZA_HILO(_valor_) secuencia_hilo = secuencia[_valor_]; temporizador_secuencia_hilo = 0; if(secuencia_hilo == temporizador_secuencia_hilo) {
#define PAUSA_HILO } temporizador_secuencia_hilo++; if(secuencia_hilo == temporizador_secuencia_hilo) {
#define TERMINA_HILO(_valor_) } secuencia[_valor_]++; if(secuencia[_valor_] > temporizador_secuencia_hilo) secuencia[_valor_] = 0;NUMERO_DE_HILOS habría que sustituir por la cantidad deseada, generalmente suelen ser 2 o 3 hilos generalmente.
La pregunta del momento:
¿Y esto para qué?Pues para lo siguiente:
Tenemos un pic que necesita hacer varios cálculos intensos (como una conversión analógico digital, por ejemplo) que requieren varios cientos de ciclos de reloj y varios cálculos más livianos (ligeros) que muestren en pantalla los resultados, por ejemplo.
El código sería algo tal que así:
int main(void)
{
while(1)
{
ConversionA_D1();
ConversionA_D2();
calculo_ligero1();
calculo_ligero2();
MostrarEnPantalla();
}
return 0;
}Se tendría que en cada iteración siempre hace 2 conversiones analógico-digital (como se había especificado en el ejemplo) y muestra en pantalla 3 cálculos ligeros (no estaba inspirado para poner un nombre). Esto es un problema cuando se requiere mostrar en pantalla, como se había especificado en el ejemplo, de forma muy frecuente, mediante esta forma no se podría hacer eficiente y siempre se obtendrían "parones" en la visualización, no siendo una programación eficiente y por tanto, si cobráis por un diseño, no siendo pagados como es debido.
¿Cómo solucionar este entuerto? Pues dividiendo, de forma más o menos inteligente, los procesos para que se produzcan, bajo hilos de programación en paralelo.
int main(void)
{
while(1)
{
// Hilo 1: la conversión analógico digital
COMIENZA_HILO(1);
ConversionA_D1(); // Cálculo extenso
PAUSA_HILO
ConversionA_D2(); // Más cálculo extenso
TERMINA_HILO(1);
// Hilo 2: las sumas
COMIENZA_HILO(2);
calculo_ligero1();
PAUSA_HILO
calculo_ligero2();
/*PAUSA_HILO
calculo_ligero3();
PAUSA_HILO
calculo_ligero4();*/ // Podría seguir añadiéndose más PAUSA_HILO sin problemas
TERMINA_HILO(2);
MostrarEnPantalla(); // Prioridad máxima
}
return 0;
}Aquí se muestra una implementación mediante los #defines antes mencionados. Se ha dado prioridad máxima a MostrarEnPantalla() por que podría decirse que ha sido el requisito que se nos ha pedido.
Forma de funcionar: MostrarEnPantalla() se ejecuta cada iteración, cada 2 iteraciones se ejecuta 1 de las 2 ConversionA_D y lo mismo con los cálculos ligeros, que como se muestra no hay limitaciones en cuanto a añadir pausas se tratase.
Consumo de tiempo:
- COMIENZA_HILO(n) = 7-8 Instrucciones PIC
- PAUSA_HILO = 5-6 Instrucciones PIC
- TERMINA_HILO(n) = 6 Instrucciones PIC
Espero que os sirva de utilidad.
Un saludo.