Realizar acciones paralelas en un pic

Hola a todos. La verdad se me hace un poco dificil explicar cual es mi duda pero alla voy. Quisiera saber si es posible ( y de ser asi como hacerlo) realizar dos instrucciones o acciones en forma paralela en un pic cualquiera sea este. Por ejemplo mientras se escanea un teclado, paralelamente a esto, el pic realice otras tareas como puede ser controlar leds o displays.
bueno se que mi explicacion no ha sido buena. espero haya un adivino que entienda lo que quiero hacer.

PD: Si lo llevamos al plano humano seria como estar caminando y comiendo a la vez. No paramos de caminar mientras caminamos sino que lo hacemos simultaneamente. (bueno una mujer pensara lo contrario)

Gracias Saludos amigos
 
Algo parecido seria controlar los leds o displays en el programa principal y escanear el teclado por interrupcion
 
Hola a todos. La verdad se me hace un poco dificil explicar cual es mi duda pero alla voy. Quisiera saber si es posible ( y de ser asi como hacerlo) realizar dos instrucciones o acciones en forma paralela en un pic cualquiera sea este. Por ejemplo mientras se escanea un teclado, paralelamente a esto, el pic realice otras tareas como puede ser controlar leds o displays.
bueno se que mi explicacion no ha sido buena. espero haya un adivino que entienda lo que quiero hacer.

Dado que los PICs tiene un único nucleo de procesamiento, ejecutar dos instrucciones "en paralelo" es imposible. Lo que sí puedes hacer un lograr ejecución concurrente, donde cada tarea tiene asignada un tiempo de ejecución y un pequeño proceso se encarga de conmutar entre ellas lo suficientemente rápido como para lograr la "apariencia" de ejecución simultánea.
Hacerlo en C es muy fácil si usás el CCS, ya que tenés que agregar algunas directivas de preprocesador para el uso de RTOS y estructurar en programa en funciones perfectamente definidas en base a las tareas a realizar concurrentemente.
Si solo manejás assembler....no tengo idea de como puede hacerse, pero seguro que es posible.
 
justo ese es mi caso soy analfabeto en C. supongo que la idea de conmutar una accion en un corto tiempo daria la impresion de ser ejecutada simultaneamente. Pero si quisiera por ejemplo ejecutar un contador donde se necesita precision a nivel de milisegundos y paralelamente a esto escanear si una tecla se apreto o no para saltar a otra rutina seria esto posible de alguna forma?

claro debe serlo pero no se me ocurre en estos momnetos como..¿habra que tener en cuenta los ciclos que demora en realizar una instruccion y calcular todo eso?
 
Claro, en realidad en los pic no podes hacer nada en simultaneo, sí podes hacer cosas muy rápido como si fuera en simultaneo para nosotros. El pic realiza de a una instrucción por vez.

Sin embargo existe una forma de hacer cosas en "paralelo" cuando sea necesario hacerlo usando interrupciones. Las interrupciones son llamadas al procesador para atender alguna situación en particular que vos podes seleccionar, ej algun periférico listo para recibir o transmitir, fin de conteo de un TIMER, etc. Cuando aparece una interrupcion el MCU primero termina de realizar la instrucción que estaba haciendo y despues se dedica a atender la interrupción. Cuando termina de atender la interrupción vuelve al programa principal y continúa con la instrucción siguiente. En los pic las interrupciones y la forma en que la MCU las atiende son programadas por el usuario. Las interrupciones se programan con la ayuda del registro INTCON del pic.

En tu caso podrías programar un TIMER para que cada cierto tiempo genere una interrupción y verifique el estado de algun puerto o lo que sea que necesites.
Esto permitirá que tu programa corra independientemente de la interrupción.


Sino, en lugar de complicarte con interrupciones, podes simplemente utilizar un bucle donde estes permanentemente haciendo las dos cosas en "paralelo" que vos querias hacer. Aunque no se van a realizar en simultaneo, practicamente lo es porque sucede muy rapido.

Espero que te sirva la info!
 
entonces si llamo a una interrupcion el contador seguiria trabajando igual y no le afectaria ??
se podria conseguir esto (llamar a una interrupcion) con el watchdog?? o estoy muy perdido?
 
Utiliza unta interrupción para que ingrese cada cierto tiempo por ejemplo 100ms.
Variables globales int contTarea1, contTarea2;
Variables globales bool banderaTarea1, banderaTarea2;
Dentro de la interrupción:
PHP:
  //Como la interrupción entra cada 100ms banderaTarea1 se activa a 1 S.
  If(contaTarea1++>=10)
  {
    banderaTarea1 = true;
    contaTarea1 =0;
  }
  //Como la interrupción entra cada 100ms banderaTarea2 se activa a 4 S.
  If(contaTarea2++>=40)
  {
    banderaTarea1 = true;
    contaTarea2 =0;
  }
Dentro de Main:
PHP:
While(true)
  {
     If(banderaTarea1 = true)
     {
       banderaTarea1 = false;
       //Escaneo teclado
     )
     If(banderaTarea2 = true)
     {
      banderaTarea2 = false;
      //Muestro datos en el display
     )
  }
 
Última edición:
podes usar uno de los TIMERS como contador y poner un bucle para que esté permanentemente leyendo el pin que te interesa mientras el TIMER cuenta. Creo que no te haria falta usar interrupciones.
 
entonces si llamo a una interrupcion el contador seguiria trabajando igual y no le afectaria ??
se podria conseguir esto (llamar a una interrupcion) con el watchdog?? o estoy muy perdido?

Efectivamente... cuando el PIC atiende una interrupcion no detiene la ejecucion de los otros modulos... a menos que se lo ordenes....
 
el watchdog no te serviría porque lo que genera es el reset del pic, en lugar de una interrupción si no me equivoco. Igualmente un TIMER es practicamente lo mismo que el watchdog, solo que te sirve para generar una interrupción.
 
gracias amigos ahora estoy un poco mas tranquilo.. eclipse al ver el codigo que pusiste me doy cuenta que debo si o si aprender c en algun momento...

Sera muy complicado que la cuenta que realice se visualice en unos displays por ejemplo? creo que no, solo habra que tener cuidado con el tiempo que toman las instrucciones para visualizar en los displays cierto??
 
Sammaael:
Mejor explicanos específicamente que es lo que necesitas hacer concurrentemente, por que si nó, todos estamos ofreciendo soluciones a las adivinanzas.
Si necesitas atender un periférico externo, la forma mas simple es mediante interrupciones, asumiendo que el periférico es capaz de interrumpirte y que no debes hacer eso para muchos periféricos diferentes, por que vas a terminar con un lío de software que no vas a entenderlo mas allá de media hora luego de escribirlo.

Si son tareas sin vinculación externa y temporizadas, con restricciones en los tiempos de duración y accionamiento preemptivo, te recomiendo usar el RTOS por que en un par de minutos vas a tener todo el problema resuelto....lo que significa que tenés que estudiar C.

Por otra parte, que sepas C es casi una obligación, por que desperdiciar el tiempo programando en assembler cosas que las resolvés en un par de minutos con un compilador C...no es una cosa muy coherente...
 
Es muy facil realmente hacer dos o varias tareas concurrentemente (pseudoparalelismo) utilizando el algoritmo round robbin.

Y la mejor forma de hacerlo, o al menos donde tienes mayor control, es con assembler. Hice algo igual pero para AVR. Este puede ejecutar 4 hilos y cada uno de ellos tiene su propia pila y sus propios registros.

Para hacerlo, necesitas entender muy bien el uso de la pila, ya que la pila o stack es la pidra angular para ello. Tambien una cantidad generosa de ram.

Te doy la pista.
El timer, cada 1 ms. Cada que arranque el timer, metes los registros a stack, y por ultimo el apuntador del stack a una localidad fija. Despues en otra localidad fija donde tienes el otro apuntador del stack lo cargas, recuperas los registros del stak y al dar regreso de interrupcion, regresara a la instruccion de la siguiente tarea puesto que de ahi fue llamada la ultima vez que estuvo la aplicacion ejecutandose. Es muy facil de hacer pero un poco de comprender si no estas acostumbrado a usar como calzon a un microcontrolador.
 
gracias ezevalla y tienes razon tendre que aprender C....

Lo que queria hacer era basicamente medir un tiempo de reaccion. La idea sencillamente es asi: se tiene una luz que al encender (aca se inicia el cronometro) se debe presionar apresuradamente un pulsador (aca termina el cronometro) y visualizar el tiempo transcurrido en forma real, es decir que al encender la luz, se inicie la cuenta de un cronometro y esta se visualize "en vivo" (que vea los numeritos corriendo como locos en el display) hasta que aprete el pulsador donde ahi se detenga la cuenta. i duda radica en que miestras se realiza el conteo del cronometro de que forma puedo verificar si se presiona o no el pulsador. La idea es hacer una cronometro del orden de los milisegundos lo as preciso posible o almenos aceptablemente precisos para la aplicacion de medir tiempos de aplicacion.
Se que seguramente ustedes sabran como hacerlo y probabemente tengan el codigo de algo similar, pero mi idea es diseñarlo a modo de ejercicio y asi aprender un poquito mas
Gracias
 
Los pics traen interrupcion por cambio de estado en el puerto B en RB0 o entre RB4 y RB7, hay programas en los que todo se realiza solo por interrupciones
Depende de que pic utilices
 
... (la) duda radica en que miestras se realiza el conteo del cronometro de que forma puedo verificar si se presiona o no el pulsador. ...
Para eso (en un pic 16F84) ponés el botón de set/reset en el pin RB0 y activás su
interrupción (bit R0IE en el registro INTCON).
Te quedan 7 bits del registro PORTB para manejar 7 segmentos.
Con el registro PORTA manejás los cátodos (hasta 4, vas cómodo).
El contador de tus tiempos y los retardos necesarios los debés implementar
mediante registros de usuario.
En realidad el pic sólo estará contando (y mostrando el nro en el display)
hasta que se produzca la interrupción y se detenga el conteo.
La implementación de eso en assembler puede no ser elemental, pero
tampoco es cosa del otro mundo.
Es más fácil en C pero perdes un poco de control de la resolución temporal.

La resolución del timer va a depender de cuántas instrucciones tenga que
ejecutar desde que salta a la rutina de interrupciones y hasta detener el conteo.
En C ese número lo fija el compilador, en assembler lo fijas vos.
Con un cristal de 20 MHz y el prescaler en 1, cada instucción simple tarda 200 ns.
 
Última edición:
Muchas gracias amigos es de mucha ayuda toda su informacion!! Creo que hare este proyecto en assembler para practicar un poco mas el lenguaje (solo llevo como 1 mes programando pic) y luego veo que hago aprendiendo C..

de nuevo muchas gracias cualquier otra idea es bien recibida de seguro sera util a todos los que nos iniciamos en pic
 
Atrás
Arriba