Autor Tema: Controlar led por puerto serial  (Leído 4622 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Controlar led por puerto serial
« 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;
      }   
             
   
           
     
   }
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #1 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

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #2 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!!!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #3 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. }

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #4 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:

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #5 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

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #6 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

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #7 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


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #8 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. }

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #9 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. }

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #10 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?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #11 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.
« Última modificación: 14 de Julio de 2016, 02:18:16 por KILLERJC »

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #12 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

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #13 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

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #14 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


 

anything