TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Marttyn en 22 de Febrero de 2007, 20:14:15

Título: deshabilitar interrupciones
Publicado por: Marttyn en 22 de Febrero de 2007, 20:14:15
hola! tengo una pequeña dudilla de nada...
estoy haciendo un programa que tiene que estar pendiete de un boton... y para no dejar el micro en un bucle infinito le puse una interrupcion externa... ahora, quiero que una vez que se ejecute la interrupcion no pueda ser interrumpida por presionar otra vez el boton antes de que acabe la ejecucion de la primera...
es decir, lo que quiero es que al pulsar un boton ocurran unas cosas, pero esas cosas no se puedan interrumpir si vuelvo a presionar el boton. estuve pensado y no se si se podria deshabilitar las interrupciones dentro de una interrupcion, asi:
Código: [Seleccionar]
#int_ext
boton(){
disable_interrupts(int_ext);

CODIGO

enable_interrupts(int_ext);
}

void main(void)
{
   enable_interrupts(int_ext);      //activar interrupcion externa
   ext_int_edge(L_TO_H);         //configuracion:interrupcion solo de LO a HIGH
   enable_interrupts(GLOBAL);      //todas las interrupciones activadas
}

es esto posible?
esta bien empleado?
gracias!!!!  :mrgreen:
Título: Re: deshabilitar interrupciones
Publicado por: maunix en 22 de Febrero de 2007, 23:00:27
Si el GIE está deshabilitado, no ocurrirá ninguna interrupción.

Los pics 16F son "monointerrupción", solo pueden atender una por vez.  Si llega otra cuando atendió la primera no se interrumpirá la ejecución del software.

Al ocurrir una interrupción, el pic modifica el Program Counter y queda en 0x0004.  También deshabilita el GIE, con lo cual no ocurrirá otra interrupción.

Cuando sales del vector de interrupción, debes hacer un RETFIE que precisamente significa "Retornar de la interrupción y habilitar las interrupciones" .

Saludos
Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 23 de Febrero de 2007, 10:47:39
Como te dijo Maunix los pic16 tienen un solo vector de intrrupciones ubicado en 0x0004, eso quiere decir que cuando cualquier interrupción se produce, el micro espera a que termine la instrucción que está ejecutando en ese momento, mete el contador de programas en la pila y luego cambia el contador de programas para la dirección 0x0004. Este proceso hace que la ejecución del código comience en 0x0004 y es en este lugar donde tienes que discriminar cual fue la interrupción que entró.

Puede darse el caso de que hayan varias interrupciones habilitadas y marcadas a la vez, entonces aquellas que pongas primero en la lisa de preguntas serán las más prioritarias. Este mecanismo funciona más o menos así:

Cada fuente de interrupción tiene un registro de habilitación (pude ser un bit o más de uno dependiendo de como se configure la IT y de su tipo), un circuito de detección y una bandera de interrupción (sirve para marcar que las condiciones para la IT ocurrieron). Cada uno de estos elementos juega un papel en el mecanismo de IT, sin embargo es la bandera la que determina si la IT se produjo o no, normalmente cuando entras en la dirección 0x0004, el procesador deshabilita TODAS las IT (modificando GIE) y cuando retornas con RETFIE, la vuelve a habilitar, si durante la ISR se produjo otra IT, entonces se vuelve a entrar en 0x0004 y así hasta que no quede ninguna IT, pero esto a veces no es deseable porque puedes demorar mucho tiempo atendiendo una IT y otra más prioritaria puede entrar sin que se atienda debidamente, por ejemplo en conversor AD puede hacer varias conversiones que se pierdan mientras atiendes otra IT.

La idea anterior es que durante la atención a una IT, otra no pueda ser atendida. Sin embargo puede darse el caso de que el compilador de C habilite nuevamente las IT cuando entras en la ISR, para que otra IT pueda interrumpir mientras atiendes a una que llegó antes, entonces tendrías dos IT anidadas, eso puede ser deseable, pero en el caso de una tecla no lo es porque estarías bajo los efectos del rebote, para evitar este único efecto y mantener el resto de las IT habilitadas (permitir el anidamiento de IT), solamente debes cambiar la configuración de la IT asociada a tu tecla para que esté deshabilitada, mientras mantienes el resto habilitadas (el conversor AD, el puerto serie, etc). Si lo que deseas es que nada te interrumpa mientras atiendes la tecla, entonces deshabilitas todas las IT a traves de GIE.

Este análisis debes hacerlo cuidadosamente porque puede darse el caso de que se afecten otras partes de tu programa. Por ejemplo si entra un dato por el puerto serie y estás atendiendo a la tecla, lo cual te puede tomar unos 30ms para eliminar el rebote y demás, puede que pierdas un grupo de datos del puerto serie si tienes TODAS las IT deshabilitadas, sin embargo si solamente deshabilitas la IT de la tecla y entran los datos por el puerto serie, podrás atender a esta IT más prioritaria dentro de la IT de la tecla y no perder los datos. Piensa y busca la solución adecuada a tu problema

Reinier

Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 23 de Febrero de 2007, 11:52:15
 :shock:
ufff.... me acabais de dar un repaso que todavia estoy intentando recuperarme  :z)
No entendi ni papa
esperad que voy a ponerme a investigar un poco...
...
...
...
OK!  :-/
Ahora entiendo un 7% mas que la primera vez que lei vuestras respuestas...
Lei un datasheet y algo que encontre por internet...
Primero, IT es la abreviacion de interrupcion, no? y GIE habilitada o deshabilitada es como poner enable/disable_interrupts(global)?
La GIE como comentais, se deshabilita cuando hay una interrupcion?
Yo solo quiero que se deshabilite la interrupcion externa para que no se pueda volver a apretar el boton mientras se ejecuta. pero quiero que sigan funcionando las interrupciones por tmr, adc o lo que sea.
no se como implementar esto que me comentais, ni si tengo que poner ¿retfie? al final de las instrucciones de mi interrupcion
alguna ayudita mas?  :mrgreen:
Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 23 de Febrero de 2007, 12:34:06
disable_interrupts (INT_EXT)  te deshabilita la interrupción externa y con enable_interrupts (INT_EXT)  la vuelves a habilitar. Que no se te olvide volver a habilitar la IT cuando atiendas a la tecla o adios a la tecla

Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 23 de Febrero de 2007, 13:04:01
entonces el codigo que puse en el primer post seria correcto....
deshabilitar las int_ext cuando entro en la interrupcion, y habilarlas en la ultima linea de codigo de esa int?
salu2 y gracias
Título: Re: deshabilitar interrupciones
Publicado por: maunix en 23 de Febrero de 2007, 13:36:10
entonces el codigo que puse en el primer post seria correcto....
deshabilitar las int_ext cuando entro en la interrupcion, y habilarlas en la ultima linea de codigo de esa int?
salu2 y gracias

Si el PIC entra en la interrupción se deshabilita el GIE.  Entonces, no hay necesidad de deshabilitar nada.

Saludos


Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 23 de Febrero de 2007, 14:18:37
Si pero el quiere mantener el resto de las interrupciones habilitadas mientras atiende la interrupción de la tecla (INT_EXT), así que debería hacer un código más o menos así

Código: C++
  1. /* Esta es mas o menos la funcion de atender la IT externa, nota como esta se
  2. encarga solamente de poner una bandera en '1' y deshabilita esta misma IT para
  3. luego retornar. Cuando sales de la ISR GLOBAL, todas las IT quedan nuevamente
  4. habilitadas, es tarea del programa principal atender a la tecla. Es decir: eliminar
  5. el rebote, leer puertos y demas cosas que hay que hacer cuando te aprietan una tecla
  6. no debe ser tarea de la funcion de atencion de la IT porque la idea de un buen
  7. diegno utilizando IT es que las rutinas de IT sean cortas y que solamente cambien
  8. algunos parametros o banderas para que otra parte del programa se haga cargo de
  9. procesar esas informaciones.
  10.  
  11. Otra razon que obliga a que las subrutinas de atencion a IT sean cortas es porque
  12. en casos como este de la tecla debes eliminar rebotes y lo mejor para hacerlo, desde
  13. mi punto de vista, es emplear un Timer y ese segnor tambien trabaja con IT. Entonces
  14. volvemos al asunto de dejar en manos del programa principal la atencion de las
  15. tareas que hay que hacer cuando se apriete una tecla
  16. */
  17. #INT_EXT
  18. void int_ext_isr(void)
  19. {
  20.  disable_interrupts(INT_EXT); //deshabilitar la IT externa
  21.  
  22.  FlagTecla = 1; //marcar la tecla como oprimida
  23.  
  24. }
  25.  
  26. /*
  27. Luego en el programa principal es donde habilitas nuevamente la IT, una vez que
  28. hayas atendido la tecla, para que cuando vuelvan a apretar la tecla se pueda
  29. procesar nuevamente
  30. */
  31.  
  32. void main(void)
  33. {
  34.   ... //Codigo que no atiende la tecla
  35.  
  36.  if(FlagTecla and Paso_el_Rebote)  //Preguntar por la tecla y si ya paso el tiempo del rebote
  37.     {
  38.      ... //Codigo para procesar la tecla
  39.      FlagTecla = 0;  //Poner las banderas en el estado de tecla no apretada y rebote no procesado
  40.      Paso_el_Robote = 0;
  41.      enable_interrupts(INT_EXT); //Ya se puede procesar otra tecla
  42.     }
  43.    
  44.  ...  //Codigo que no atiende la tecla  
  45.    
  46. }


Esta no es la única forma que existe para hacer eso, se pueden utilizar otros mecanismos, más o menos elaborados para ello. Por ejemplo puedes hacer todo el proceso de atender la tecla dento de int_ext_isr() y habilitar las interrupciones globales para que haya anidamiento de IT, pero esa técnica te puede traer problemas, sobre todo porque la pila de los PIC es bastante pequeña y es un recurso que debemos vigilar constantemente. También puedes utilizar un RTOS que te puede ayudar a simplificar mucho el trabajo, etc.

Tú eres quien tiene que decidir cual es el mejor método para hacer el trabajo o cual te da mejores resultados sin complicarte mucho.

Un saludo Reinier
Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 17 de Marzo de 2007, 17:45:55
Código: C++
  1. #INT_EXT
  2. void int_ext_isr(void)
  3. {
  4.  disable_interrupts(INT_EXT); //deshabilitar la IT externa
  5.  
  6.  FlagTecla = 1; //marcar la tecla como oprimida
  7.  
  8. }
  9.  
  10. void main(void)
  11. {
  12.   ... //Codigo que no atiende la tecla
  13.  
  14.  if(FlagTecla and Paso_el_Rebote)  //Preguntar por la tecla y si ya paso el tiempo del rebote
  15.     {
  16.      ... //Codigo para procesar la tecla
  17.      FlagTecla = 0;  //Poner las banderas en el estado de tecla no apretada y rebote no procesado
  18.      Paso_el_Robote = 0;
  19.      enable_interrupts(INT_EXT); //Ya se puede procesar otra tecla
  20.     }
  21.    
  22.  ...  //Codigo que no atiende la tecla  
  23.    
  24. }

reiniertl, entiendo el codigo que pusiste. lo que no me queda claro es si al salir de int_ext_isr vuelve al inicio del main, segun leo el codigo parece que debe ser asi, sino no veo la manera de que funcione. y de ser asi, porque al acabar el isr continua al inicio del main?
lo que tampoco me queda claro es lo de Paso_el_rebote, en que momento se pone a 1? de hecho no comprendo muy bien que es el rebote y como evitarlo
gracias y salu2
Título: Re: deshabilitar interrupciones
Publicado por: vszener en 18 de Marzo de 2007, 09:06:56
Como ya te han dicho, cuando se produce una interrupción, el GIE se pone a 0, por lo que no puede haber ninguna otra interrupción.

Aunque si te queda más claro poner el disable_interrupts(); lo pones, simplemente lo que haces es reescribir un 0 al GIE.


Suerte!!! ;)
Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 19 de Marzo de 2007, 14:50:54
reiniertl, creo que ya entendi tu codigo!  :mrgreen:
le faltaria un bucle infinito al main para que este constantemente verificando si se produjo o no una INT_EXT, no?
Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 19 de Marzo de 2007, 16:01:27
Parece que no has comprendido bien el mecanismo de interrupción. Te lo explico un poco mejor:

Imagina que el PIC está ejecutando un programa, ejecutará las líneas de código de forma secuencial, hasta que encuentra un salto a alguna parte del código, por esta razón es que main() debe tener un ciclo infinito, para asegurar que al terminar de ejecutar las líneas de código de main(), el programa comience nuevamente por el principio. Si no se hace así el PIC continuará "ejecutando" código hasta que llegue al final de su espacio de direcciones y se quede zoombie.

Bien, lo anterior explica como funciona un programa cualquiera, si tienes intención de atender periféricos con un programa así, se dice que estás atendiendo al proceso por encuesta, ya que en alguna parte del código preguntarás por el estado de algun registro para en función del resultado ejecutar una acción. Este mecanismo es ineficiente y muchas veces no puede ser utilizado porque hay procesos que duran muy poco en el tiempo y necesitan ser atendidos rápidamente, para ello existen los mecanismos de interrupción.

Cada vez que el PIC ejecuta una instrucción, antes de cargar la que le sigue, primero chequea si se ha producido una interrupción, si es así, entonces mete el Contador de programas  (CP) en la pila (el CP apunta a la instrucción que debe ejecutar el procesador en el programa normal), y carga una dirección fija en el CP, en este caso 0x0004h y carga la instrucción que se encuentra en esta dirección. Has entrado en la ISR (Interrupt Service Routine), cuando terminas de ejecutar este código, la última intsrucción tiene que ser retfie, para que el PIC saque de la pila el valor del CP que estaba antes de que se atendiera a la interrupción.

Claro el compilador de C, hace parte del trabajo por tí y te evita tener que fajarte con salvar registros que utilizas dentro de una ISR, pone por tí código para retornar de la interrupción, etc.

La directiva #int_ext le dice el compilador que la función que le sigue en el código es la subrrutina de atención a la interrupción externa. Esto quiere decir que cuando se produzaca esta interrupción se ejecutará el código de esta función y cuando se termine de ejecutar se retorna al punto del programa donde se produjo la interrupción. Cuando se produce una interrupción: ¡NADIE SABE!, lo que si debemos asegurar es que se atienda lo más rápido posible.

Lo otro de trabajar con interrupciones es que la sbrutina de atención debe ser LO MÁS CORTA POSIBLE, eso quiere decir que debemos separar lo esencial del proceso de atención de las cosas que debemos hacer en consecuencia. Por ejemplo una ISR para atender al converor AD, quizás solamente deba leer el dato del resultado, cambiar el canal y dar nuevamente inicio de conversión, el programa principal se encargará de procesar los datos y hacer algo con el resultado de ese procesamiento, no debemos poner todo el código de actuación ante una interrupción en la ISR porque muchas de las cosas que hagamos ante una interrupción no requieren que se actúe de inmediato, aunque si hay que atender las cosas esenciales a la mayor brevedad posible.

En el caso de lo que pretendes hacer la INT_EXT te permite saber que se apretó una tecla, y con eso le indicas al programa principal (el que está dentro de main()) que se apretó la tecla para que sea este código quien actúe en consecuencia. El uso de la Interrupción te permite que no se pierda la pulsación de una tecla, ya que si tu programa está haciendo algo que consume tiempo, es posible que la tecla se apriete y se suelte y tu PIC no se de cuenta, aunque esto es poco probable que ocurra con una tecla, hay procesos que son bastante rápidos y eso puede ocasionar que se pierda información o no se tengan encuenta determinados procesos.

Reinier
Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 19 de Marzo de 2007, 16:32:05
pues con todo esto me has aclarado un monton de oscuros rincones de los pics. pero con lo de un bucle infinito en el main para ver si acurrio una int_ext me referia que el bucle lo que comprobaba era si se habia marcado el flag de que hubo una interrupcion y que se actue en consecuencia, aunque lo principal como marcar el flag, comprobar el adc, guardar un valor o lo que sea lo haga la propia interrupcion.
Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 19 de Marzo de 2007, 17:26:34
En lo anterior estás en lo cierto, lo que hace main() es comprobar si se produjo la INT y la INT_EXT lo que hace es setear la bandera.
Título: Re: deshabilitar interrupciones
Publicado por: hammerEQ en 05 de Abril de 2007, 19:12:24
Hola. hablando de las interrupciones y todo eso. Estoy empezando a trabajar en el PICC de CCS y tengo una duda. ¿ para que las banderas de interrupciones(p.e. TOIF, RBIF, INTF, etc) cambien de estado, es necesario que las opciones de habilitacion de las interuciones esten habilitadas ? (cosa que no pasa con assembler o el C de HI TECH, ya que las banderas se activaran asi no esten habilitadas las interruciones). Gracias.
Título: Re: deshabilitar interrupciones
Publicado por: vszener en 07 de Abril de 2007, 07:08:05
Los flags se habilitan igualmente sólo que no se accede al servicio de interrupción a no ser que esté habilitado.


Suerte!!! ;)
Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 09 de Enero de 2009, 01:42:28
Hola! despues de casi una año de abrir este hilo aprendi un monton de cosas gracias a todos ustedes!
Ahora se un poquito mas de las interrupciones, pero sigo teniendo una duda...
Cuando configuro las interrupciones del pic (al principio del main), hace falta que deshabilite TODAS las interrupciones que tiene el PIC y que no uso? o cuando inicias el PIC por defecto vienen todas deshabilitadas?
En el datasheet no encontre nada de esto  :?
Podria configurar directamente INTCON y PIE1 (en el 12f683) pero no es tan directo como los enable/disable_interrupts...
Salu2!
Título: Re: deshabilitar interrupciones
Publicado por: reiniertl en 09 de Enero de 2009, 03:02:28
Busca en la sección donde hablan del reset, seguro encontrarás información al respecto, sobre todo los registros involucrados en este tipo de procesos, a los que se le suele asignar valores específicos en el reset.

Saludos
Reinier
Título: Re: deshabilitar interrupciones
Publicado por: jacrmr en 09 de Enero de 2009, 07:25:55
Cuando se hace power-on reset están todas desactivadas. Sin embargo, hay diferentes tipos de reset. En la hoja de datos siempre aparece el estado que tienen los registros inmediatamente después de hacer power-on reset (arriba de caba bit de un registro aparece algo como "R/W - 1" o similar, el número después del guión indica el estado después de power-on reset). En algunas hojas de datos aparece una sección especial con todos los resgistros y sus valores ante power-on reset, watchdog reset, brown-out reset, etc.
Título: Re: deshabilitar interrupciones
Publicado por: Marttyn en 09 de Enero de 2009, 22:52:33
efectivamente, los 2 tienen razon!
en la seccion del reset hay una tablita con todos los valores de los registros despues de un POR, MCLR, WDT, etc.
tambien en "memory organization", en la seccion de cada registro, arriba viene el valor despues de un POR, precedido por un R, W o RW
 :-/ :-/ :-/
al principio pensaba que los datasheets  eran aburridos y muy pesados, pero cada vez me parecen mas interesantes... incluso, ver que tenian 200 mas paginas me echaba para atras... pero una vez que te familiarizas con el, la verdad no son tantas paginas!  :-)
Gracias y salu2!
Título: Re: deshabilitar interrupciones
Publicado por: pajaro128 en 03 de Febrero de 2009, 01:59:53
HOLA ..hace poco q estoy con los pic ..y mucho menos con el CCS...hice un programa y tengo un problema con la INT_EXT ..no entra (todo esto simulado en PROTEUS ......el programa es una lavadora de picadoras ...hace la presentacion ..presiono "INICIO" ...mueve una cinta tramsportadora ..si encuentra picadora ...llena de agua ..calienta agua ..y comienza a lavar ....si no encuentra picadora ..pone un mensaje de final de proceso y me indica cuantas picadoras se lavaron ....
PD:hay intrucciones q no se usar ...acepto consejos para mejorar el codigo ..gracias

//------Directivas para el compilador--------
#include <16f877a.h>                      //PIC utilizado
#fuses XT,NOWDT,NOPROTECT,NOLVP           //Configuramos los fuses
#use delay (clock=4000000)                //Oscilador a 4Mhz
#use fast_io(A)                           //Optimizamos E/S del PORTA
#use fast_io(B)                           //Optimizamos E/S del PORTB
#use fast_io(C)                           //Optimizamos E/S del PORTC
#use fast_io(D)                           //Optimizamos E/S del PORTD
#use fast_io(E)                           //Optimizamos E/S del PORTE
#INCLUDE "lcd.c"                          //Incluyo LCD.C
                       

//------Prototipos de funciones-----

void corrigo_salida(void);
void lcd_saludo_inicial(void);
void inicio_proceso(void);
void busca_pica1(void);
void nohay_pica1(void);
int  lleno_agua(void);
int  calor_agua(void);
int  lavando_pica1(void);
void busca_pica2(void);
int  lavando_pica2(void);

//VARIABLES GLOBALES

int vhaypica1  ; //ESTAS VARIABLES VOY HACER Q SI HAY UN 0 ES POR Q NO  SE CARGO EL           
int vhayagua   ; //AGUA(CARGO EL AGUA Y PONGO UN 1 EN LA VARIABLE)Y ASI CADA VES Q PASA
int vhaycalor  ; //UNA PICA SI LA VARIABLE ESTA EN 1 NO CARGA PASA AL LAVADO(O SIMPLEMENTE
int paso_pica1 ; //LO USO CON EL SENSOR 1 DE PICA Y VA A PASAR UNA SOLA VES Y DESPUES ME
long cant_pica  ;


//INTERRUPCION RB0---------------------

#INT_EXT
void isr(void) {
         delay_ms(20); //antirrebote
 
           
         if(input(PIN_A3)==1) output_low(PIN_C0);          //paro la cinta
         if(input(PIN_A3)==1)vhaypica1=1;
         if(input(PIN_A3)==1) cant_pica++;
         }
  //  #INT_EXT
//void
//{
//if (!bit_test(PIN_A2)) {
  // output_bit( PIN_A2, 0);
   //Ddelay_ms(1000);
   //direccion=1;   
/// }
// }
                     
//------Programa principal----------
void main(void) {
//------Puertos y pines-------------

   #byte PORTA=0x05
   #byte PORTB=0x06
   #byte PORTC=0x07
   #byte PORTD=0x08
   #byte PORTE=0x09
   set_tris_A(0xFF);   //PUERTO A como entrada.
   set_tris_B(0xFF);   //PUERTO B como entrada. 
   set_tris_C(0x90);   //PUERTO C 0,1,2,3 como salida y 4,5,6,7 como entrada
   set_tris_D(0x108);  //PUERTO D  como salida
   set_tris_E(0xFF);   //PUERTO E 3 como entrada y 0,1,2,4,5,6,7 como salida

   
    ext_int_edge(L_TO_H);
    disable_interrupts(INT_EXT);
    disable_interrupts(GLOBAL);
   
//-----Inicializo el LCD y muestro el saludo inicial----------

   corrigo_salida();
   lcd_init();
   lcd_saludo_inicial();     
   inicio_proceso();
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);     
   busca_pica1();
   lleno_agua();     
   calor_agua();   
   lavando_pica1(); 
   buscapica2:
   busca_pica2();
   lavando_pica2();
   goto buscapica2;
}
 
//------------------------------------------------------------------------------
//FUNCIONES
//------------------------------------------------------------------------------
//----IMPRIME SALUDO INICIAL.-------------

void lcd_saludo_inicial(void) {
         
      lcd_gotoxy(4,1);
      Lcd_putc ("LAVAMATIC");         //Escribo en la primera fila
      lcd_gotoxy(3,2);                //columna 4, fila 2
      Lcd_putc( "VERSION 1.00");      //Escribo en la segunda fila
      delay_ms(2000);                 //Espero tres segundos   
}
//-----INICIO PROCESO------------------

void inicio_proceso(void) {

      disable_interrupts(INT_EXT);
      Lcd_putc( "\f");               //Limpio pantalla
      salta:
      lcd_gotoxy(3,1);
      Lcd_putc ("PRESIONE EL");       //Escribo en la primera fila
      lcd_gotoxy(2,2);                //columna 2, fila 2
      Lcd_putc( "BOTON *INICIO*");    //Escribo en la segunda fila
     
      if(!input(PIN_A0))            //COMPRUEBO Y NIEGO LA SALIDA DE RA0
           {goto  salta; }       
      Lcd_putc( "\f");                //Limpio pantalla     
}

//----PONGO EN CERO PINES--------------

void corrigo_salida(void)
    {     
      output_low(PIN_C0);   
      output_low(PIN_B0);
      output_low(PIN_B1);
      output_low(PIN_B2);
      output_low(PIN_B3);       
    }       

//-------BUSCA PICA1--------------------

void busca_pica1(void) {
long i ;
     
     Lcd_putc( "\f");                       //Limpio pantalla       
     lcd_gotoxy(5,1);
     Lcd_putc ("BUSCANDO");             //o en la primera fila
     lcd_gotoxy(2,2);                         //columna 4, fila 2
     Lcd_putc( "PICADORA  1");    //Escribo en la segunda fila
     enable_interrupts(GLOBAL);
     enable_interrupts(INT_EXT);
     output_high(PIN_C0);                   //mueve cinta tramsportadora
     delay_ms(2500);                         //Espero tres segundos
     
      for (i==0 ;  i<1600 ; i++)       //con el valor de i regulo el tiempo
             {                         //en que busco la pica
               delay_ms(50); 
               IF(vhaypica1==1)        //si hay vhaypica1=1 ,i=2536 y salgo
                {                      //del bucle for
                  i=1600;                           
                }             
             }                 
              IF(vhaypica1==0)                 
                 nohay_pica1();       


//-------BUSCA PICA2--------------------
void busca_pica2(void) {
long i ;

     Lcd_putc( "\f");                       //Limpio pantalla
     lcd_gotoxy(5,1);
     Lcd_putc ("BUSCANDO");             //o en la primera fila
     lcd_gotoxy(3,2);                   //columna 4, fila 2
     cant_pica++;
     printf(lcd_putc, "PICADORA  %lu",cant_pica);    //Escribo en la segunda fila 
     cant_pica--;
     enable_interrupts(GLOBAL);
     enable_interrupts(INT_EXT); 
     output_high(PIN_C0);                 //mueve cinta tramsportadora
     delay_ms(2500);                         //Espero tres segundos   
     
      for (i==0 ;  i<80 ; i++)       //con el valor de i regulo el tiempo
             {                         //en que busco la pica
               delay_ms(80); 
               IF(vhaypica1==1)        //si hay vhaypica1=1 ,i=2536 y salgo
                {                      //del bucle for
                  i=80;                           
                }             
             }                 
               IF(vhaypica1==0)                 
                 nohay_pica1();       
}
//--------LLENO DE AGUA------------------

int lleno_agua(void) {
   
      Lcd_putc( "\f");                //Limpio pantalla     
      lcd_gotoxy(4,1);
      Lcd_putc ("LLENANDO ");         //Escribo en la primera fila
      lcd_gotoxy(4,2);                //columna 4, fila 2
      Lcd_putc( "DE AGUA");           //Escribo en la segunda fila
      delay_ms(1000);                 //Espero tres segundos
      salta2:
      output_high(PIN_C1);            //conecto bomba agua
     
      if(!input(PIN_A1))              //COMPRUEBO Y NIEGO LA SALIDA DE RA0
          {goto  salta2; }   
      output_low(PIN_C1);                       //apago bomba agua   
      vhayagua  =1 ; 
      return vhayagua;
}

//----------CALIENTO AGUA--------------------
int calor_agua(void) {

      Lcd_putc( "\f");                  //Limpio pantalla     
      lcd_gotoxy(3,1);
      Lcd_putc ("CALENTANDO ");         //Escribo en la primera fila
      lcd_gotoxy(4,2);                  //columna 4, fila 2
      Lcd_putc( "EL AGUA");             //Escribo en la segunda fila
      delay_ms(1000);                   //Espero tres segundos
      salta3:
      output_high(PIN_C2);              //enciendo resistencias
     
      if(!input(PIN_A2))                //COMPRUEBO Y NIEGO LA SALIDA DE RA0
           {goto  salta3; }
      output_low(PIN_C2);               //apago resistencias   
           vhaycalor=1;
      return vhaycalor;
}

//----------LAVANDO PICADORA 1-----------------
int  lavando_pica1(void){
long  cant_pica1 ;

      cant_pica1 = cant_pica ;
      disable_interrupts(GLOBAL);            //deshabilito las interrupciones
      disable_interrupts(INT_EXT);            //deshabilito las interrupciones     
      Lcd_putc( "\f");                       //Limpio pantalla     
      lcd_gotoxy(3,1);
      Lcd_putc ("LAVANDO  ");            //Escribo en la primera fila
      lcd_gotoxy(3,2);                       //columna 4, fila 2
      printf(lcd_putc, "PICADORA  %lu",cant_pica1);  //Escribo en la segunda fila 
      delay_ms(100);
      output_high(PIN_C3);                   //conecta leva, cepi y agua presion
      delay_ms(6000);                        //Espero seis segundos
      output_low(PIN_C3);                    //apago leva y cepillo   
      vhaypica1=0;
      return paso_pica1;
}

//----------LAVANDO PICADORA 2-----------------
int lavando_pica2(void){     
long  cant_pica1 ;

      cant_pica1 = cant_pica ;
      disable_interrupts(GLOBAL);            //deshabilito las interrupciones
      disable_interrupts(INT_EXT);            //deshabilito las interrupciones     
      Lcd_putc( "\f");                       //Limpio pantalla     
      lcd_gotoxy(3,1);
      Lcd_putc ("LAVANDO  ");            //Escribo en la primera fila
      lcd_gotoxy(4,2);                       //columna 4, fila 2
      printf(lcd_putc, "PICADORA  %lu",cant_pica1); //Escribo en la segunda fila 
      delay_ms(100);
      output_high(PIN_C3);                   //conecta leva, cepi y agua presion
      delay_ms(6000);                        //Espero seis segundos
      output_low(PIN_C3);                    //apago leva y cepillo     
      vhaypica1=0;
      return vhaypica1;         
}

//------NO HAY PICA1-------------------
void nohay_pica1(void) {
long  cant_pica1 ;

      cant_pica1 = cant_pica ;   
      disable_interrupts(GLOBAL);   //deshabilito las interrupciones     
      disable_interrupts(INT_EXT);
    //  disable_interrupts(INT_RTCC);
      output_low(PIN_C0);           //apago la cinta
      repito:
      Lcd_putc( "\f");              //Limpio pantalla     
      lcd_gotoxy(3,1);
      Lcd_putc ("NO HAY JUEGO");    // la primera fila
      lcd_gotoxy(3,2);              //columna 4, fila 2
      Lcd_putc( "DE PICADORA");     //bo en la segunda fila
      delay_ms(1000);               //Espero 10   segundos   
      Lcd_putc( "\f");              //Limpio pantalla
      lcd_gotoxy(5,1);
      Lcd_putc ("PROCESO");         //o en la primera fila
      lcd_gotoxy(4,2);              //columna 4, fila 2
      Lcd_putc( "TERMINADO");       //Escribo en la segunda fila
      delay_ms(1000);               //Espero 10   segundos
      Lcd_putc( "\f");                       //Limpio pantalla     
      lcd_gotoxy(1,1);
      Lcd_putc ("TOTAL PICADORAS");            //Escribo en la primera fila
      lcd_gotoxy(2,2);                       //columna 4, fila 2
      printf(lcd_putc, "LAVADAS  %lu",cant_pica1); //Escribo en la segunda fila 
      delay_ms(2000);
      goto repito;                  //repitoel mensaje

}