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

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

Desconectado kapotik

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

Desconectado KILLERJC

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

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #17 en: 15 de Julio de 2016, 19:43:42 »
Me podrias poner un ejemplo con interrupcion por favor.

Gracias

Desconectado KILLERJC

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

Desconectado kapotik

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

Desconectado kapotik

  • PIC16
  • ***
  • Mensajes: 121
Re:Controlar led por puerto serial
« Respuesta #20 en: 30 de Julio de 2016, 21:24:12 »
Adjunto la simulacion en proteus por si alguien quiero probarlo

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Controlar led por puerto serial
« Respuesta #21 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", 
« Última modificación: 31 de Julio de 2016, 00:44:43 por KILLERJC »

Desconectado kapotik

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

Desconectado KILLERJC

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


 

anything