TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: kapotik en 04 de Julio de 2016, 22:36:15

Título: Controlar led por puerto serial
Publicado por: kapotik en 04 de Julio de 2016, 22:36:15
Buenas, quiero controlar desde la PC atraves de puerto serial el estado de los led conectados a las salidad de un PIC16f877a, estos estados son 3, prendido, apagado y parpadeante.
Por ejemplo si le envio: A0 (apagado) A1 (encendido) AP (parpadea).
Tengo el siguiente codigo que lo unico que puedo controlar es prender y apagar, pero no logro que parpadee, ademas no puedo poner el dato como yo quiero, solo admite un solo caracter no dos.

Porfa si alguien me puede guiar se lo agradecere

Saludos

Código: [Seleccionar]
#include <16f877a.h>
#fuses hs,nowdt,noprotect,noput
#use delay (clock=20M)
#USE RS232(baud=9600,rcv=pin_c7,bits=8,parity=N)
#use standard_io(c) 
 
void main()
{
   char valor;
    set_tris_b(0b00000000);
   output_b(0b00000000);
   while(true)
   {
     
      valor=getc();
      switch(valor)
      {
         case '1': output_toggle(pin_b0);break;
         case '2': output_toggle(pin_b1);break;
         case '3': output_toggle(pin_b2);break;
         case '4': output_toggle(pin_b3);break;
      }   
             
   
           
     
   }
}
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 05 de Julio de 2016, 09:07:33
2 cosas para decirte:

- El micro recibe de a 1 caracter por vez. el getc() es una accion bloqueante asi que si esta en el loop, se va a detener ahi hasta que reciba algo.

- Para facilidad deberias usar una interrupcion de recepcion de la UART.

En tu recepcion podrias verificar que cuando llegue una A, lo proximo que llegue se guarde, tambien vas a tener que verificar que sea exactamente un 0,1 o una P. Luego en tu main harias:

Código: C
  1. while(1)
  2. {
  3.         switch(valor)
  4.         {
  5.         case '0':
  6.                 output_low(pin_b0);
  7.                 break;
  8.         case '1':
  9.                 output_high(pin_b1);
  10.                 break;
  11.         case 'P':
  12.                 output_toggle(pin_b2);
  13.                 break;
  14.         default: break;
  15.         }
  16.         delay_ms(250);          // Para que se vea el
  17. }

Eso seria lo mas SIMPLE que podrias hacer. "valor" es asignado desde la rutina de interrupcion
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 07 de Julio de 2016, 00:37:46
Gracias  KILLERJC, siguiendo tus consejos he modificado el codigo y ya funciona como yo quiero, pero lo que no logro entender es como se hace para que el led se quede parpadeando y el pic pueda seguir haciendo otra cosa, pego lo que tengo.

Código: C
  1. #include <16f877a.h>
  2. #fuses hs,nowdt,noprotect,noput
  3. #use delay (clock=20M)
  4. #USE RS232(baud=9600,rcv=pin_c7,bits=8,parity=N)
  5. #use standard_io(c)  
  6.   //DEFINICION DE CONSTANTES
  7.  
  8.    
  9.  
  10. //DECLARACION DE VARIABLES
  11.  
  12.    char c1=0,c2=0;
  13. void main(VOID)
  14. {
  15.    //PROGRAMA PRINCIPAL
  16. //*******************
  17.    WHILE (TRUE)
  18.    {
  19.    c1=0,c2=0;
  20.    c1=getch();
  21.    //*******************************************************************************
  22.      if (c1=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  23.         {
  24.         c2=getch();
  25.  //*******************************************************************************      
  26.       if (c2=='1')
  27.                {
  28.                 // delay_us(100);
  29.                  output_high(pin_B0);
  30.                 // output_low(pin_B2);
  31.                 // delay_us(100);
  32.                 }
  33.    
  34.       if (c2=='2')
  35.                {
  36.                 // delay_us(100);
  37.                 // output_high(pin_B0);
  38.                  output_low(pin_B0);
  39.                 // delay_us(100);
  40.                 }
  41.       if (c2=='P')
  42.                {
  43.                 delay_ms(300);
  44.                 output_high(pin_B0);
  45.                 delay_ms(300);
  46.                 output_low(pin_B0);
  47.                 //output_toggle(pin_B0);
  48.                 //delay_ms(300);
  49.                 }
  50.                
  51.      }
  52.    }
  53. }

les recuerdo que lo que quiero es que una ves recibido el comando correspondiente se quede parpadeando hasta que se le indique lo contrario.

Saludetes!!!
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 07 de Julio de 2016, 08:43:45
Te dejo otro codigo, este solo espera un 1, un 0 , o una P. Sin la A

Código: C
  1. while(1)
  2. {
  3.         if(kbhit())
  4.         {
  5.                 valor = getc();
  6.         }
  7.  
  8.         switch(valor)
  9.         {
  10.                 case '0':
  11.                         output_low(pin_b0);
  12.                         break;
  13.                 case '1':
  14.                         output_high(pin_b1);
  15.                         break;
  16.                 case 'P':
  17.                         output_toggle(pin_b2);
  18.                         delay_ms(250);          // Para que se vea el
  19.                         break;
  20.                 default:
  21.                         break;
  22.         }
  23. }
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 07 de Julio de 2016, 12:18:02
Graciad killerjc, pero me voy a quedar con el ultimo que postee, ya que en el codigo final necesito decodificar una cadena de varios carecteres y este me sirve bastante bien, solo me falta lque el led se quede parpadeando hasta que se le indique lo contrario.
Si bien de esta manera parpadea:

Código: C
  1. if (c2=='P')
  2.                {
  3.                 delay_ms(300);
  4.                 output_high(pin_B0);
  5.                 delay_ms(300);
  6.                 output_low(pin_B0);
  7.          
  8.                 }


...solo lo hace una vez y yo quiero que siga parpadeando hasta que se le indique lo contrario, el C no es mi lenguaje
pero recuerdo haber hecho parpadear un led mientras el micro hace otra cosa hace años y era mucho mas facil que en assembler
pero como solo estaba probando el lenguaje no guarde el codigo.  :oops:
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 11 de Julio de 2016, 20:11:26
Como se hace para poner un byte en alto y luego chequearlo, se me ocurre que cuando reciba la "P" coloque en alto un byte para que luego se pueda testear dentro del while y si esta en alto que vuelva a parpadear el led se entiende?
Si me pueden explicar como se hace porfis!!!!

Saludos
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 11 de Julio de 2016, 23:39:22
depende, si es una variable por ejemplo un

int8 valor;

con bit_test(valor,numero de bit aca);
Ejemplo si quiero saber si el bit 1 de la varaible valor esta en 1, lo hago con:

if( bit_test(valor,1) ) { }

-----------

Ahora si es un puerto, es un problema, por que CCS comienza en STANDARD_IO lo cual si vos lees lo transforma en entrada, y si escribis lo convierte a salida. Para evitar eso podes cambiar ese modo FAST_IO, tambien tenes que setear el tris

#USE FAST_IO(b)

set_tris_b(0b00010000);

Y luego podes usar el input_pin() sin ningun problema que no lo va a convertir en entrada.

Todo esta mas explicado en el manual de CCS
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 12 de Julio de 2016, 00:32:59
Gracias Killerjc por tomarte un tiempito para contestarme, me parece que no me he expresado bien, jejeje, mi mente va mas rapido que mis dedos para escribir,
en assembler lo hago asi

Código: ASM
  1. bcf             0x27,1          ; pongo a cero el registro completo
  2.                 bcf             0x27,2          ; por el momento uso una sola posicion
  3.                 bcf             0x27,3
  4.                 bcf             0x27,4
  5.                 bcf             0x27,5
  6.                 bcf             0x27,6
  7.                 bcf             0x27,7
  8.                 bcf             0x27,0

luego para ponerlo en alto lo hago asi

Código: ASM
  1. bsf             0x27,0

y luego para testearlo asi

Código: ASM
  1. btfsc           0x27,0

bueno lo mismo quiero hacer pero en C
la idea es la siguiente para que se quede parpadeando

Código: C
  1. while(1)
  2. {
  3.  
  4. if (c2=='P')
  5.                {
  6.                
  7. aca           bsf               0x27,0
  8.          
  9.                 }
  10.  
  11. y luego     btfsc               0x27,0
  12.                  {
  13.                 delay_ms(300);
  14.                 output_high(pin_B0);
  15.                 delay_ms(300);
  16.                 output_low(pin_B0);
  17.                  }
  18.   }

Saludos

Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 12 de Julio de 2016, 01:27:43
entonces es una variable, supongamos que la variable de 8 bits que tenes se llama "valor", voy a hacer el equivalente en ASM y C de CCS

Para hacer lo primero en ASM es mejor hacer:

Código: ASM
  1. CLRF 0x27

en C mejor:

Código: C
  1. valor = 0;

------------------------------------------------

Código: ASM
  1. BSF 0x27, 0

en C:

Código: C
  1. bit_set(valor,0);

y para ponerlo a 0 es bit_clear()

----------------------------------------

Código: ASM
  1. btfsc            0x27,0

en C:

Código: C
  1. if(bit_test(valor,0) == 0 )
  2. {
  3. }
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 14 de Julio de 2016, 00:06:23
no entiendo por que no me funciona.
haber si e entendido bien como funciona el C, todo lo que esta dentro de WHILE se va a repetir infinitas veces, esto es asi?
si se repite infinitas veces,  si yo coloco la variable en alto y queda asi, por que cuando le digo que testee si esta en alto solo lo hace una sola ves?

Código: C
  1. //DECLARACION DE VARIABLES
  2.    int8 valor;
  3.    
  4.    char c1=0,c2=0;
  5. void main(VOID)
  6. {
  7.    //PROGRAMA PRINCIPAL
  8. //*******************
  9.    valor = 0;
  10.    WHILE (TRUE)
  11.    {
  12.    c1=0,c2=0;
  13.    c1=getch();
  14.    
  15.    //*******************************************************************************
  16.      if (c1=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  17.         {
  18.         c2=getch();
  19.  //*******************************************************************************      
  20.       if (c2=='1')
  21.                {
  22.                 output_high(pin_B0);
  23.                 }
  24.    
  25.       if (c2=='2')
  26.                {
  27.                 output_low(pin_B0);
  28.                 bit_clear(valor,0);
  29.                 }
  30.       if (c2=='P')
  31.                {
  32.                 bit_set(valor,0);
  33.                 }
  34.                      
  35.      }
  36.       if(bit_test(valor,0) == 1 )
  37.               {
  38.                
  39.                 delay_ms(300);
  40.                 output_high(pin_B0);
  41.                 delay_ms(300);
  42.                 output_low(pin_B0);
  43.                }          
  44.    }
  45.    
  46.  
  47. }
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 14 de Julio de 2016, 00:28:07
esto esta bien hecho?
Código: C
  1. int8 valor;

me parece que no.....

si yo quiero usar la posicion o registro ( no se cual es la palabra) 0x27 como lo pongo?
eso seria una variable?
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 14 de Julio de 2016, 02:14:02
En C no te manejas con registros. Solamente pensas en variables, donde estan ubicadas en el micro no es de tu interes.

Lo que vos necesitas es un bit nomas. un flag. Pero ese no es tu problema. Yo ya te dije que tu problema esta en el getch();

si te manejas con el ASM te lo explico con ASM el getch es algo asi:

Código: C
  1. c2 = getch();

equivalente a:

Código: ASM
  1. GETCH
  2.    BTFSS  PIR1, RXIF       ;Supongamos que es el indicador de que un caracter llego
  3.    GOTO   GETCH
  4.    MOVF   RXREG, W
  5.    MOVWF C2

Es decir tenes un loop infinito hasta que llegue el dato, sino no sale de ahi.

Entonces tu programa hace esto...

- Comienza el while
- Se queda esperando que llegue un dato, no sale de ese getch()
- Si recibe una 'A' entra al if
- Si entra al if queda atrapado ahora con el otro getch(), supongamos que pones la 'P'
- Sale del primer if ( c1 == 'A' )
- Como se puso en 1 ese bit ahora entra al if con los delays, ejecuta eso
- Se termina el while y comienza todo de nuevo.

Observaras que cada ves que comienze el while va a estar encerrado en el getch() y por lo tanto no va a realizar lo de enceder y apagar el led con el delay ese.

Tu programa funcionaria si: Presionas primero la 'A' , luego la 'P' y luego tenes que presionar CUALQUIER letra ( menos la 'A' ) para que encienda y apague el led de B0, cada ves que la presiones sale del getch, y pregunta por ese bit, la cual va a estar en 1 por ponerle el "AP" antes, y va a hacer los delays, pero luego va a esperar nuevamente para que presiones la tecla.

-------------------------------------------------------

yo pense que querias usar para cambiar algun bit es especial de algun numero. Pero veo que intentas hacer una "flag". para eso C tiene las variables tipo bool o int1 en CCS, que son de 1 bit

Tu MISMO programa pero escrito de otro modo:

Código: C
  1. //DECLARACION DE VARIABLES
  2. int1 flag = false;
  3.    
  4. void main(VOID)
  5. {
  6.         //PROGRAMA PRINCIPAL
  7.         /*******************
  8.  
  9.         WHILE (TRUE)
  10.         {
  11.                 //*******************************************************************************
  12.                 if (getch()=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  13.                 {
  14.                         switch(getch())
  15.                         {
  16.                         case '1':
  17.                                 ouput_high(PIN_B0);
  18.                                 break;
  19.                         case '2':
  20.                                 ouput_low(PIN_B0);
  21.                                 flag = false;
  22.                                 break;
  23.                         case 'P':
  24.                                 flag = true;
  25.                                 break;
  26.                         default:
  27.                                 break;
  28.                 }
  29.  
  30.                 if(flag)                       
  31.                 {
  32.                         delay_ms(300);
  33.                         output_high(pin_B0);
  34.                         delay_ms(300);
  35.                         output_low(pin_B0);
  36.                 }          
  37.         }
  38. }

Es decir tiene los mismos problemas, pero escrito de otra forma.
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 14 de Julio de 2016, 10:25:27
Cuando decis con los mismos problemad te referis a que se queda en el getch?
Cual es la alternativa al getch?

Saludos
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 14 de Julio de 2016, 12:37:19
Te lo habia puesto en un codigo antes:


Código: C
  1. if(kbhit())
  2.         {
  3.                 valor = getch();
  4.         }

el kbhit() devuelve true si es que hay un caracter esperando en la UART ( ya recibido) lo cual el getch no se quedaria esperando, y si no hay nada devuelve false, lo cual no entraria al getch y seguiria su camino
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 15 de Julio de 2016, 02:27:41
Código: C
  1. int8 valor;
  2.    char c1=0,c2=0;
  3. void main(VOID)
  4. {
  5.    //PROGRAMA PRINCIPAL
  6. //*******************
  7.    WHILE (TRUE)
  8.    {
  9.    c1=0,c2=0;
  10.     if(kbhit())
  11.         {
  12.                
  13.                 c1=getch();
  14.         }
  15.  
  16.        
  17.    
  18.    
  19.    //*******************************************************************************
  20.      if (c1=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  21.         {
  22.         c2=getch();
  23.  //*******************************************************************************      
  24.       if (c2=='1')
  25.                {
  26.                 output_high(pin_B0);
  27.                 }
  28.    
  29.       if (c2=='2')
  30.                {
  31.                 output_low(pin_B0);
  32.                 bit_clear(valor,0);
  33.                 }
  34.       if (c2=='P')
  35.                {
  36.                 bit_set(valor,0);
  37.                 }
  38.      
  39.                
  40.      }
  41.      if(bit_test(valor,0) == 1 )
  42.                {
  43.                 delay_ms(300);
  44.                 output_high(pin_B0);
  45.                 delay_ms(300);
  46.                 output_low(pin_B0);
  47.                }          
  48.    }
  49. }

funciona pero una ves que entra en el parpadeo cuando esta en los dalays no atiende el puerto serial por ende no recibe nada y a no ser que justo lo reciva cuando empieza de nuevo el while
no sale del parpadeo
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 15 de Julio de 2016, 02:46:31
Si ya se me lo dijiste  :oops: "- Para facilidad deberias usar una interrupcion de recepcion de la UART."
trate de hacerlo pero realmente no lo entendi, algunas cosas no supe donde colocarlas....


Código: C
  1. #include <16f877a.h>
  2. #fuses hs,nowdt,noprotect,noput
  3. #use delay (clock=20M)
  4. #USE RS232(baud=9600,rcv=pin_c7,bits=8,parity=N)
  5. #use standard_io(c)
  6.  
  7. char c1=0,c2=0;
  8. #int_rda
  9. void rda_isr()
  10. {
  11.   c1=getch();
  12. }
  13. int1 valor;
  14.    
  15.  void main()
  16.  {
  17.  
  18.  enable_interrupts(INT_RDA);
  19.  enable_interrupts(GLOBAL);
  20.  
  21.  
  22.    //PROGRAMA PRINCIPAL
  23. //*******************
  24.    WHILE (TRUE)
  25.    {
  26.    c1=0,c2=0;
  27.     if(kbhit())
  28.         {
  29.                
  30.                 c1=getch();
  31.         }
  32.  
  33.        
  34.    
  35.    
  36.    //*******************************************************************************
  37.      if (c1=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  38.         {
  39.         c2=getch();
  40.  //*******************************************************************************      
  41.       if (c2=='1')
  42.                {
  43.                 output_high(pin_B0);
  44.                 }
  45.    
  46.       if (c2=='2')
  47.                {
  48.                 output_low(pin_B0);
  49.                 bit_clear(valor,0);
  50.                 }
  51.       if (c2=='P')
  52.                {
  53.                 bit_set(valor,0);
  54.                 }
  55.      
  56.                
  57.      }
  58.      if(bit_test(valor,0) == 1 )
  59.                {
  60.                 delay_ms(300);
  61.                 output_high(pin_B0);
  62.                 delay_ms(300);
  63.                 output_low(pin_B0);
  64.                }          
  65.    }
  66. }
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 15 de Julio de 2016, 03:22:36
Algo medio bruto realizado ( sin interrupciones)

Código: C
  1. //DECLARACION DE VARIABLES
  2.  
  3. int1 flag = false;
  4. char temp[2];
  5. int8 i;
  6.    
  7. void main(VOID)
  8. {
  9.         //PROGRAMA PRINCIPAL
  10.  
  11.         WHILE (TRUE)
  12.         {
  13.                 if( kbhit() )
  14.                 {
  15.                         temp[i] = getch();
  16.                         if( i > 1 ) i = 0;
  17.                 }
  18.  
  19.                 if (temp[0]=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  20.                 {
  21.                         switch(temp[1])
  22.                         {
  23.                         case '1':
  24.                                 ouput_high(PIN_B0);
  25.                                 temp[0] = 0;
  26.                                 temp[1] = 0;
  27.                                 break;
  28.                         case '2':
  29.                                 ouput_low(PIN_B0);
  30.                                 flag = false;
  31.                                 temp[0] = 0;
  32.                                 temp[1] = 0;
  33.                                 break;
  34.                         case 'P':
  35.                                 flag = true;
  36.                                 temp[0] = 0;
  37.                                 temp[1] = 0;
  38.                                 break;
  39.                         default:
  40.                                 break;
  41.                 }
  42.  
  43.                 if(flag)                        
  44.                 {
  45.                         delay_ms(300);
  46.                         output_high(pin_B0);
  47.                         delay_ms(300);
  48.                         output_low(pin_B0);
  49.                 }          
  50.         }
  51. }
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 15 de Julio de 2016, 19:43:42
Me podrias poner un ejemplo con interrupcion por favor.

Gracias
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 15 de Julio de 2016, 22:59:58
No se si funcionara, tal ves tenga algun que otro error, ademas agrego algunas otras cosas mas para que te vayas acostumbrando o averigues.

Código: C
  1. //Esto no es una variable es una definicion de un enum
  2. enum Estados_enum
  3. {
  4.         PRIMER_LETRA,
  5.         SEGUNDA_LETRA
  6. };
  7.  
  8. //Esta es una declaracion de una variable
  9. enum Estados_enum Estados = PRIMER_LETRA;
  10. int1 flag = false;
  11.  
  12. #int_rda
  13. void rda_isr()
  14. {
  15.         switch(Estados)
  16.         {
  17.                 case PRIMER_LETRA:
  18.                         if( getch() == 'A' ) Estados = SEGUNDA_LETRA;
  19.                         break;
  20.  
  21.                 case SEGUNDA_LETRA:
  22.                         switch(getch())
  23.                         {
  24.                                 case '1':
  25.                                         output_high(PIN_B0);
  26.                                         Estados = PRIMERA_LETRA;
  27.                                         break;
  28.                                 case '2':
  29.                                         output_low(PIN_B0);
  30.                                         flag = false;
  31.                                         Estados = PRIMERA_LETRA;
  32.                                         break;
  33.                                 case 'P':
  34.                                         flag = true;
  35.                                         Estados = PRIMERA_LETRA;
  36.                                         break;
  37.                                 default:
  38.                                         // Quitar el comentario si queres que al escribir A6, se deba volver a escribir la A
  39.                                         //Estados = PRIMERA_LETRA;
  40.                                         break;
  41.                         }
  42.                         break;
  43.  
  44.                 default:
  45.                         // Si hay algun problema, directamente leemos y se descarta el dato
  46.                         getch();
  47.                         break;
  48.         }
  49. }
  50.  
  51.    
  52. void main(VOID)
  53. {
  54.         enable_interrupts(INT_RDA);
  55.         enable_interrupts(GLOBAL);
  56.  
  57.         //PROGRAMA PRINCIPAL
  58.  
  59.         WHILE (TRUE)
  60.         {
  61.                 if(flag)                        
  62.                 {
  63.                         delay_ms(300);
  64.                         output_high(pin_B0);
  65.                         delay_ms(300);
  66.                         output_low(pin_B0);
  67.                 }          
  68.         }
  69. }
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 30 de Julio de 2016, 21:16:57
guenitas luego de un breve receso vuelvo a retomar el tema de controlar leds por puerto serial, lo que he logrado hasta ahora es usando interrupción para comunicación serial prenderlo apagarlo y que se quede parpadeando, pero solo enviando un solo carácter, "1" prende, "2" apaga y "P" parpadea, como la idea es controlar todas las salidas del pic16F877a necesito recibir una cadena por ejemplo "A2P" donde la "A" seria el puerto, en este caso el A, "2" el pin del puerto y "P" la acción, en este caso parpadear. Antes de implementar la interrupcion me funcionaba.
Este es el codigo con interrupcion pero para un solo caracter, que funciona bien.

Código: C
  1. int8 valor=0;
  2. char c1=0;
  3. #int_rda
  4. void rda_isr(void){
  5.    c1 = getch();
  6.    
  7. }
  8.  
  9.  void main(void){
  10.  
  11.  
  12.  
  13.  while (true){
  14.    
  15.     enable_interrupts(INT_RDA);
  16.     enable_interrupts(GLOBAL);
  17. if (c1=='1')
  18.                {
  19.                 output_high(pin_B0);
  20.                 }
  21.          if (c1=='2')
  22.                {
  23.                 output_low(pin_B0);
  24.                 bit_clear(valor,0);
  25.                 }        
  26.          if (c1=='P')
  27.                {
  28.                 bit_set(valor,0);
  29.                }
  30.    
  31.          if(bit_test(valor,0) == 1 )
  32.               {
  33.                 output_high(pin_B0);
  34.                 delay_ms(300);
  35.                 output_low(pin_B0);
  36.                 delay_ms(300);
  37.                }          
  38.   }
  39. }


Entonces para recibir 2 caracteres se me ocurrio esto, pero tengo que enviarle 2 veces el comando para que lo reconosca y cuando le pido que parpadee lo hace pero despues empieza con cosas raras, no quiere salir o se queda prendido.

Código: C
  1. int8 valor=0;
  2. char c1=0,c2=0;
  3. #int_rda
  4. void rda_isr(void){
  5.    c1 = getch();
  6.    c2 = getch();
  7. }
  8.  
  9.  void main(void){
  10.  
  11.  
  12.  
  13.  while (true){
  14.    
  15.     enable_interrupts(INT_RDA);
  16.     enable_interrupts(GLOBAL);
  17.     if (c1=='A')   // CHEQUEO SI EXISTE ALGUN MENSAJE DE ACCION O RESPUESTA
  18.                 {
  19.          if (c2=='1')
  20.                {
  21.                 output_high(pin_B0);
  22.                 bit_clear(valor,0);
  23.                }
  24.          if (c2=='2')
  25.                {
  26.                 output_low(pin_B0);
  27.                 bit_clear(valor,0);
  28.                 }        
  29.          if (c2=='P')
  30.                {
  31.                 bit_set(valor,0);
  32.                }
  33.          
  34.                }
  35.      if(bit_test(valor,0) == 1 )
  36.               {
  37.                 output_high(pin_B0);
  38.                 delay_ms(200);
  39.                 output_low(pin_B0);
  40.                 delay_ms(200);
  41.               }          
  42.         }
  43. }


saludos
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 30 de Julio de 2016, 21:24:12
Adjunto la simulacion en proteus por si alguien quiero probarlo
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 31 de Julio de 2016, 00:38:59
Entonces para recibir 2 caracteres se me ocurrio esto, pero tengo que enviarle 2 veces el comando para que lo reconosca y cuando le pido que parpadee lo hace pero despues empieza con cosas raras, no quiere salir o se queda prendido.

Código: C
  1. void rda_isr(void){
  2.    c1 = getch();
  3.    c2 = getch();
  4. }

Voy a intentar explicarte donde esta el error, a pesar que creo que ya te lo explique.

Cuando entra a la interrupcion es por que recibio 1 "un" solo caracter. ¿Por que tenes problemas? por el getch().
El getch es una funcion BLOQUEANTE, que quiere decir esto? te lo hago en un codigo para que lo entiendas:

Tu codigo:
Código: C
  1. c1 = getch();
Equivalente:
Código: C
  1. while(NoHayDato == 1) {}
  2. c1 = DatoQueLLego

Basicamente es eso lo que tenes dentro del getch, es decir tenes un while, y que mientras no exista nada que llego se va a quedar ahi encerrado en ese while. Cuando llegue recien algo es cuando lo pone en c1 por ejemplo.

Ahora cuando es 1 solo no hay problema. Por que si recordas entra a la interrupcion cuando llega 1 dato. por lo tanto el primer getch SI o SI tiene dato, pero el segundo no! hasta que no le envies otro.

Si quisieras recibir de esa forma, es decir  {A,B} Luego el bit {0-7} y Luego la accion {Z,X,P}, siendo Z de encendido, X de apagado, y P de parpadeo. Entonces haria una maquina de estado. Lo primero a recibir seria A o B para indicar el puerto. Una de las cosas que hice fue hacer que todos los comandos sean SI o SI de 3 letras.


Código: C
  1. char BufferEntrada[4];  // Buffer donde vamos a ir almacenando lo que va llegando
  2. char BufferCopia[4];    // Buffer que es el que va a leer el main
  3. char recibido;          // Donde se va a guardar el char
  4. bool DatoListo          // Para indicarle al main que hay un dato
  5.  
  6.  
  7. // Codigo de interrupcion:
  8.  
  9.  
  10. recibido = getch();
  11. switch(Estado)
  12. {
  13. case 0:
  14.         if (recibido=='A' || recibido == 'B')
  15.         {
  16.                 Estado++;
  17.                 BufferEntrada[0]=recibido;
  18.         }
  19.         break;
  20. case 1:
  21.         if(recibido >= '0' && recibido <= '9')
  22.         {
  23.                 Estado++
  24.                 BufferEntrada[1] = recibido;
  25.         }
  26.         else
  27.         {
  28.                 Estado = 0;
  29.         }
  30.         break;
  31. case 2:
  32.         if(recibido == 'P' || recibido == 'Z' || recibido == 'X')
  33.         {
  34.                 BufferCopia[2] = recibido;
  35.                 BufferCopia[1] = BufferEntrada[1];
  36.                 BufferCopia[0] = BufferEntrada[0];
  37.                 DatoListo = true;
  38.         }
  39.         Estado = 0;
  40.         break;
  41. default:
  42.         Estado = 0;
  43.         break;
  44.  
  45.  
  46. // Codigo del main:
  47.  
  48.  
  49.  
  50.  
  51. while(true)
  52. {
  53.         if(DatoListo==true)
  54.         {
  55.                 DatoListo= false;
  56.                
  57.                 // De ser mas puertos usar un switch en ves de ifs
  58.  
  59.                 if(BufferCopia[0] == 'A')
  60.                 {
  61.                         // Puerto A
  62.                         // Aca seteo de parpadeo y
  63.                 }
  64.                 else
  65.                 {
  66.                         // Puerto B
  67.                 }
  68.         }
  69. }
  70.  
  71.  
  72. // Codigo de interrupcion de timer
  73.  
  74. int_timer()
  75. {
  76.      // Aca cada tanto verificar cual es el que debe hacerse parpadear y cambiarle el estado.

Te dejo la parte del main y la del timer para vos, es simple de realizarlo al menos en MPLAB, en CCS puede que se complique un poco mas.
Y para que entiendas, en el main cuando DatoListo se ponga a 1 o true, quiere decir que tenes los 3 caracteres en BufferCopia Y que eso no va a cambiar hasta que lleguen otros 3 caracteres mas, de los cuales obviamente son validos.
De recibir un caracter INVALIDO volveria al comienzo. Ejemplo A2F
Al recibir la F que seria un caracter "invalido" en el codigo que propusimos, no se queda esperando que uno lo corrija, es decir envie una P por ejemplo, sino que hay que enviar todo de vuelta "A2P", 
Título: Re:Controlar led por puerto serial
Publicado por: kapotik en 31 de Julio de 2016, 14:19:55
....me doy por vencido, gracias killer por tu ayuda pero este lenguaje no es para mi.

Saludos
Título: Re:Controlar led por puerto serial
Publicado por: KILLERJC en 31 de Julio de 2016, 19:04:19
....me doy por vencido, gracias killer por tu ayuda pero este lenguaje no es para mi.

Saludos

No es por eso, es por que elegiste CCS, que tiene sus "trampas" para hacer algo un poco mas complejo.

Luego es seguirle el hilo al programa.

Y pienso que deberias comenzar por algo mas facil, tratar de crear una maquina de estado en la recepcio de la UART no es complicado, pero tiene su desafios si es que estas comenzando. Y luego lo demas tambien. Tengo otra opcion mas que puede o no ser mas facil, pero estoy mas que seguro que es ineficiente. Luego pongo el programa, no funcionando por que no tengo CCS pero para que tengas una idea.