# Comunicación serial PIC 16F1827 + Proteus



## superdog13 (Jul 3, 2015)

Estoy haciendo un código que es bastante sencillo, para probar la comunicación serial del PIC 16F1827 con interrupciones

Antes de explicar el problema, este es el esquema:







El código para el PIC de arriba:


```
#include <16f1827.h>
#fuses   XT,NOWDT,NOPROTECT,PUT,NOLVP  //ordenes para el programador
#use     delay (clock=32M)         // Fosc=32Mhz
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)

#define NO_INTERRUPCION        PIN_B3
#define SERIAL            PIN_B4
#define EXTERNO           PIN_B5 

int FLAG_EXT=0;
#INT_EXT
void ext_int(){
   disable_interrupts(GLOBAL);
   FLAG_EXT=1;
   enable_interrupts(GLOBAL);
}

int FLAG_SERIAL=0;
#int_RDA
void RDA_isr(void){
   disable_interrupts(GLOBAL);
   FLAG_SERIAL=1;
   enable_interrupts(GLOBAL);
}

void main(void){
   int ce;
   int cs;
   RESTART_WDT();
   enable_interrupts(int_ext);
   enable_interrupts(int_rda);
   ext_int_edge(L_TO_H);
   enable_interrupts(GLOBAL);
   
   while(TRUE){
      if(FLAG_SERIAL==1){
         output_low (NO_INTERRUPCION);
         output_low (EXTERNO);
         output_high (SERIAL);
         delay_ms(1000);
         output_low (SERIAL);
         FLAG_SERIAL=0;
         cs++;
      }
      else if(FLAG_EXT==1){
         output_low (NO_INTERRUPCION);
         output_low (SERIAL);
         FLAG_EXT=0;
         output_high (EXTERNO);
         delay_ms(1000);
         output_low (EXTERNO);
         ce++;
      }
      else if(FLAG_SERIAL==0 && FLAG_EXT==0){
         output_high (NO_INTERRUPCION);
         output_low (EXTERNO);
         output_low (SERIAL);
      }
   }
}
```

El código del PIC de abajo:


```
#include <16f1827.h>
#fuses   XT,NOWDT,NOPROTECT,PUT,NOLVP  //ordenes para el programador
#use     delay (clock=32M)         // Fosc=32Mhz
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)

#define NO_INTERRUPCION         PIN_B3
#define SERIAL            PIN_B4

int FLAG_EXT=0;
#INT_EXT
void intrb0()
{
   FLAG_EXT=1;
}

void main(void)
{
   int c;
   RESTART_WDT();
   enable_interrupts(int_ext);
   ext_int_edge(L_TO_H);
   enable_interrupts(GLOBAL);
   output_low (NO_INTERRUPCION);
   output_low (SERIAL);
   port_b_pullups(0b00000110);
   while(TRUE){
      if(FLAG_EXT==1){
         output_low (NO_INTERRUPCION);
         FLAG_EXT=0;
         char x="HOLA";
         putc(x,com);
         output_high (SERIAL);
         delay_ms(1000);
         output_low (SERIAL);
         c++;
      }
      do{
         output_high (NO_INTERRUPCION);
      }while(FLAG_EXT==0);
   }
}
```

Una explicación rápida del funcionamiento:


*PIC 1:*
Si no está activa ninguna interrupción, el led ROJO está encendido. Si se activa la interrupción externa (por interruptor), se enciende el led VERDE. Si se activa la interrupción por comunicación serial (por el otro PIC) se enciende el led AZUL
*PIC 2:*
Si no está activa la interrupción, el led ROJO está encendido. Si se activa la interrupción externa (por interruptor), se enciende el led AZUL y se envía un número por puerto serial al otro PIC

Para ambos PIC funciona bien tanto el led ROJO (sin interrupciones) y el led correspondiente a la activación de la interrupción externa. El problema es que o bien el PIC 2 no envía o el PIC 1 no recibe o ninguno de los dos hace nada


----------



## TRILO-BYTE (Jul 3, 2015)

el proteus trae simulacion de terminal

y se ve que NO SABES que el RS232 envia cadenas de caracteres es decir

no puedo hacer esto

char x="HOLA";

por que char X solo se carga con *1* sola letra
mientra que 

char x[5]="hola"; 

si es valido por que es una cadena de caracteres

ahora char *x="HOLA";
tambien es valido pues es un apuntador cargado con la cadena de caracteres

NO es valido hacer esto
*putc(x,com);*

pues putc como lo dice su nombre escribe *1* sola letra es decir

no podemos escribir

char *x="foros de electronica";
         putc(x);


para eso se usa la directiva *printf* que nos permite escribir una cadena entera

en el CCS encontramos una ayuda llamada *INDEX* que si la lees podrias aprender mucho si no la les estas perdido


----------



## D@rkbytes (Jul 3, 2015)

Otros detalles aparte de lo que menciona TRILO-BYTE...
Si vas a simular, no uses frecuencias de trabajo tan elevadas, usa 1 MHz o 4 MHz, porque el simulador se sobrecarga.
Ya cuando realices el montaje en físico, cambia la palabra de configuración y la frecuencia que usarás normalmente.

Los problemas por los que no funciona tu programa son varios, sobre todo en el manejo de las interrupciones.

Aquí te lo dejo funcionando en simulación y posiblemente en físico también.
Compara los cambios realizados a los programas para que puedas ver en que partes tenías los problemas.

Como nota adicional, la frecuencia de trabajo la tienes en 32 MHz, pero usaste el fuse XT en vez de HS.
Al simulador eso no le afecta porque usa la frecuencia que se le establece al microcontrolador, pero en la programación eso si es importante.


----------



## superdog13 (Jul 13, 2015)

Bueno, muchas gracias por las respuestas
La verdad solo hacía ese programa para probar que la recepción serial estuviera funcionando, porque tengo otro programa más grande en el cual debo implementarla

El programa lo que hace es recibir cierta información desde un XBee hasta otro XBee (puede ser PIC-PIC o PC-PIC) y hacer algo dependiendo de lo que recibe

Parte del programa original es el siguiente:


```
#include <16F1827.h>
#device WRITE_EEPROM = NOINT
#FUSES WDT, NOPUT, PROTECT, NOMCLR, NOCLKOUT, NOCPD, NOBROWNOUT, PLL, INTRC_IO,
#use delay(clock=32M)
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)

...

void main (void){
   int temp;
...
   ext_int_edge(L_TO_H);
   setup_timer_0(T0_INTERNAL|T0_DIV_4);
   enable_interrupts(global);
   enable_interrupts(int_ext);
   enable_interrupts(INT_TIMER0);
   while(true){      
      RESTART_WDT();
      if(kbhit(com)){
         RESTART_WDT();
         temp=recepcion_datos();  // -> -> Devuelve un entero
         ejecucion(temp);         // -> -> Actúa dependiendo del valor de la anterior función
      }
...
   }
}
```

En la función donde se reciben los datos se está haciendo siempre esto:


```
rx=getc(com);
```


Ahora, modificando el código para tener interrupción quedó de esta forma:


```
#include <16F1827.h>
#device WRITE_EEPROM = NOINT
#FUSES WDT, NOPUT, PROTECT, NOMCLR, NOCLKOUT, NOCPD, NOBROWNOUT, PLL, INTRC_IO,
#use delay(clock=32M)
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)

...

#int_RDA
void RDA_isr(void){
   RESTART_WDT();
   OUTPUT_BIT(LED2,LON);
   temp[br]=getc(com);
   br++;
   if(br==1){
      dato=temp[0];
      if(dato!=0x7E){
         temp[0]=0;
         br=0;
         recep=0;
      }
   }
   if(br==3){
      tam_tram=temp[2];
      tamano=tam_tram+3;
   }
   if(br<tamano){recep=0;}
   else if(br==tamano){recep=1;}
}
...

void main (void){
...
   ext_int_edge(L_TO_H);
   setup_timer_0(T0_INTERNAL|T0_DIV_4);
   enable_interrupts(global);
   enable_interrupts(int_ext);
   enable_interrupts(int_rda);         // Interrupción comunicación serial
   enable_interrupts(INT_TIMER0);
   while(true){
      RESTART_WDT();
// VALIDACIÓN DE RECEPCIÓN
      if(recep==1){
         RESTART_WDT();
         for(pos=0;pos<=br-1;pos++){decodificar_trama(pos,temp[pos]);}
         for(pos=0;pos<=32;pos++){temp[pos]=0;}
         temp2=recepcion_datos();
         ejecucion(temp2);
         br=0;
         temp2=0;
         tam_tram=0;
         recep=0;
      }
...
   }
}
```

Se creó una función para pasar la información del programa "principal" a la librería:


```
void decodificar_trama(int cn,int dato){
	brr[cn]=dato;
}
```

Y en la función de recepción ahora se hace lo siguiente:


```
rx=brr[0];
```

Esto con el fin de que  se pueda estar ejecutando una acción sin esperar que todos los datos necesarios para una nueva instrucción lleguen al tiempo.

Anteriormente si llegaba un dato, se paraba lo que estuviera haciendo y solamente se dedicaba a recibir todo.
Ahora la idea es que mientras reciba todos los datos que está esperando, esté ejecutando algo y luego al acabar "revise" si tiene algo pendiente por hacer (llegaron todos los datos) o se quede esperando que lleguen los datos restantes.

El problema es que con el programa modificado jamás hace nada de lo que se le envía por XBee. No se dónde pueda ser el problema porque la recepción está funcionando correctamente (como se comprobó con el ejemplo que dio inicio a este post)

Espero que me puedan ayudar


----------



## TRILO-BYTE (Jul 13, 2015)

sigo sin entender por que rayos *#use delay(clock=32M)*

que objetivo tiene si ese micro no puede manejar esa frecuencia y sobretodo por que que objetivo tiene
el programa no esta optimizado ni nada simplemente pienso que es un copy paste taringuero


----------



## D@rkbytes (Jul 13, 2015)

TRILO-BYTE dijo:


> Sigo sin entender por qué rayos *#use delay(clock=32M)
> *que objetivo tiene si ese micro no puede manejar esa frecuencia


El PIC16F1827 si puede trabajar en esa frecuencia, tanto con cristal como con el oscilador interno.

De que el programa está mal elaborado, sí que lo está.


----------



## TRILO-BYTE (Jul 14, 2015)

aaa perdon pense era el 16f887


----------



## D@rkbytes (Jul 14, 2015)

superdog13 dijo:


> El problema es que con el programa modificado jamás hace nada de lo que se le envía por XBee.
> No sé dónde pueda ser el problema porque la recepción está funcionando correctamente (como se comprobó con el ejemplo que dio inicio a este post)


Siempre que tengo algún tipo de problema al cual no le encuentro solución lógica en el programa, entro al modo de depuración ICD y voy analizando la ejecución del programa paso por paso.

Veo el valor de las variables, los registros y cómo se va ejecutando el proceso.
De esa forma se visualiza fácilmente en que parte se produce el problema.


----------



## superdog13 (Jul 14, 2015)

D@rkbytes dijo:


> Siempre que tengo algún tipo de problema al cual no le encuentro solución lógica en el programa, entro al modo de depuración ICD y voy analizando la ejecución del programa paso por paso.
> 
> Veo el valor de las variables, los registros y cómo se va ejecutando el proceso.
> De esa forma se visualiza fácilmente en que parte se produce el problema.



Primero que todo muchas gracias por la ayuda y por el tiempo que te tomaste leyendo el código

Esto no se puede hacer en el compilador (CCS) verdad ???
El código en sí es bastante extenso y la simulación no es algo fácil de hacer, pero creo que lo puedo hacer en físico prendiendo algún LED o algo así

Podrías orientarme un poco en qué partes del programa (el modificado) está mal o se podría optimizar ???


----------



## TRILO-BYTE (Jul 14, 2015)

acabo de ver un error *drastico*!

#int_RDA
void RDA_isr(void){
   RESTART_WDT();
   OUTPUT_BIT(LED2,LON);
* temp[br]=getc(com);
   br++;*
   if(br==1){
      dato=temp[0];
      if(dato!=0x7E){
         temp[0]=0;
         br=0;
         recep=0;
      }
   }
   if(br==3){
      tam_tram=temp[2];
      tamano=tam_tram+3;
   }
   if(br<tamano){recep=0;}
   else if(br==tamano){recep=1;}
}


aveces CCS no respeta esto aunque sea correcto

yo lo declarararia asi

para poder recibir una cadena de caracteres en RDA se uede hacer esto:

#include<bla bla.h>
//*char *cadena debe ser variable global se declara abajo de las cabeceras*
char *cadena; //*no sabemos cuanto mide la cadena lo declaro como apuntador*

#int_RDA
void RDA_isr(void)
{
  gets(cadena); *   //con esto leemos toda la cadena que llega en una interrupcion*
}


----------



## superdog13 (Jul 14, 2015)

Con unas modificaciones, el código quedó ahora así:


```
#int_RDA
void RDA_isr(void){
   RESTART_WDT();
   temp[br]=getc(com);
   br++;
   if(br==1 && temp[0]!=0x7E){br=0;}
   if(br==3){tamano=tam_tram=temp[2]+3;}
   if(br==tamano){
      if(!recep){
         for(pos=0;pos<=br-1;pos++){decodificar_trama(pos,temp[pos]);}
      }
      recep=1;
      br=0;
   }
}
```


```
void main (void){
...
      //CONFIGURACION INTERRUPCIONES
      ext_int_edge(L_TO_H);
      setup_timer_0(T0_INTERNAL|T0_DIV_4);
      enable_interrupts(global);
      enable_interrupts(int_ext);
      enable_interrupts(int_rda);         // Interrupción comunicación serial
      enable_interrupts(INT_TIMER0);
      manualf=read_eeprom(3);
...
   while(true){
      RESTART_WDT();
      // VALIDACIÓN DE RECEPCIÓN
      if(recep==1){
         RESTART_WDT();
         temp2=trama_espera();
         recepcion(temp2);
         temp2=0;
         tam_tram=0;
         recep=0;
      }
...
}
```

Pero sigue teniendo el mismo problema



> El problema es que con el programa modificado jamás hace nada de lo que se le envía por XBee.
> No sé dónde pueda ser el problema porque la recepción está funcionando correctamente (como se comprobó con el ejemplo que dio inicio a este post)



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



TRILO-BYTE dijo:


> * temp[br]=getc(com);
> br++;*
> 
> aveces CCS no respeta esto aunque sea correcto



No entiendo muy bien, por qué no lo hace siempre ???

Al hacerlo así con un "char" no tendría que esperar que llegue toda la información dentro de la misma vez que se activó la interrupción ???


----------



## superdog13 (Jul 14, 2015)

Estuve haciendo algunas pruebas pero sigo teniendo problemas

El circuito que tengo montado es el siguiente:







PIC 1: Arriba
PIC 2: Abajo

Y tengo estos dos códigos:

*Emisor*

```
#include <16f1827.h>
#use     delay (internal = 32MHz)         // Fosc=32Mhz
// #use     delay (internal = 4MHz)          // Fosc=4Mhz, para simulación
#use     RS232(UART1)

#define NO_INTERRUPCION       PIN_B4
#define EXTERNO               PIN_B5

int FLAG_EXT=0;
#INT_EXT
void ext_int(){
   FLAG_EXT=1;
}

void main(){
   int c=0;
   int e=0;
   enable_interrupts(int_ext);
   ext_int_edge(L_TO_H);
   enable_interrupts(GLOBAL);
   output_high (EXTERNO);
   output_high (NO_INTERRUPCION);
   delay_ms(1000);
   output_low (EXTERNO);
   output_low (NO_INTERRUPCION);
   delay_ms(1000);
   output_high (EXTERNO);
   output_high (NO_INTERRUPCION);
   delay_ms(1000);
   output_low (EXTERNO);
   output_low (NO_INTERRUPCION);
   delay_ms(1000);
   output_high (EXTERNO);
   output_high (NO_INTERRUPCION);
   delay_ms(1000);
   output_low (EXTERNO);
   output_low (NO_INTERRUPCION);
   delay_ms(1000);
   while(TRUE){
      if(FLAG_EXT==1){
         output_low (NO_INTERRUPCION);
         FLAG_EXT=0;
         switch(c){
            case 0:
               e=0x7E;
            break;
            case 1:
               e=0x00;
            break;
            case 2:
               e=0x11;
            break;
            case 3:
               e=0x90;
            break;
            case 4:
               e=0x00;
            break;
            case 5:
               e=0x00;
            break;
            case 6:
               e=0x01;
            break;
            case 7:
               e=0x03;
            break;
            case 8:
               e=0x0A;
            break;
            case 9:
               e=0x02;
            break;
            case 10:
               e=0x00;
            break;
            case 11:
               e=0x00;
            break;
            case 12:
               e=0xFF;
            break;
            case 13:
               e=0xFE;
            break;
            case 14:
               e=0x01;
            break;
            case 15:
               e=0x01;
            break;
            case 16:
               e=0x20;
            break;
            case 17:
               e=0x83;
            break;
            case 18:
               e=0x0B;
            break;
            case 19:
               e=0x01;
            break;
            case 20:
               e=0xB1;
            break;
         }
         putc(e);
         output_high (EXTERNO);
         delay_ms(1000);
         output_low (EXTERNO);
         c++;
         if(c>20){c=0;}
      }
      else if(FLAG_EXT==0)
      {
         output_high (NO_INTERRUPCION);
         output_low (EXTERNO);
      }
   }
}
```

*Receptor*


```
#include <16f1827.h>
#use     delay (internal = 32MHz)         // Fosc=32Mhz
// #use     delay (internal = 4MHz)          // Fosc=4Mhz, para simulación
#use     RS232(UART1)

#define RECEPCION       PIN_B4
#define ERROR           PIN_B5
#define ESTADO          PIN_B6 

/*
ESTADO
-> CONSTANTE: DISPONIBILE
-> APAGADO: OCUPADO
-> 2 INT: TAM_TRAMA
-> 3 INT: COMPLETO
*/

int temp[32]={0};
int br=0;
int recep=0;
int pos;
int tamano=0;

#int_RDA
void RDA_isr(void){
   output_low (ERROR);
   output_low (ESTADO);
   output_high (RECEPCION);
   temp[br]=getc();
   br++;
   if(br==1 && temp[0]!=0x7E){
      output_low (RECEPCION);
      output_high (ERROR);
      delay_ms(1000);
      output_low (ERROR);
      delay_ms(1000);
      output_high (ERROR);
      delay_ms(1000);
      output_low (ERROR);
      delay_ms(1000);
      br=0;
   }
   if(br==3){
      output_high (ESTADO);
      delay_ms(1000);
      output_low (ESTADO);
      delay_ms(1000);
      output_high (ESTADO);
      delay_ms(1000);
      output_low (ESTADO);
      delay_ms(1000);
      tamano=temp[2]+3;
   }
   if(br==tamano){
      output_high (ESTADO);
      delay_ms(1000);
      output_low (ESTADO);
      delay_ms(1000);
      output_high (ESTADO);
      delay_ms(1000);
      output_low (ESTADO);
      delay_ms(1000);
      output_high (ESTADO);
      delay_ms(1000);
      output_low (ESTADO);
      delay_ms(1000);
      for(pos=0;pos<=32;pos++){temp[pos]=0;}
      br=0;
      recep=1;
   }
}

void main(){
   enable_interrupts(int_rda);
   enable_interrupts(GLOBAL);
   output_high (RECEPCION);
   output_high (ERROR);
   output_high (ESTADO);
   delay_ms(1000);
   output_low (RECEPCION);
   output_low (ERROR);
   output_low (ESTADO);
   delay_ms(1000);
   output_high (RECEPCION);
   output_high (ERROR);
   output_high (ESTADO);
   delay_ms(1000);
   output_low (RECEPCION);
   output_low (ERROR);
   output_low (ESTADO);
   delay_ms(1000);
   output_high (RECEPCION);
   output_high (ERROR);
   output_high (ESTADO);
   delay_ms(1000);
   output_low (RECEPCION);
   output_low (ERROR);
   output_low (ESTADO);
   delay_ms(1000);
   while(TRUE){
      if(recep==1){
         recep=0;
      }
      else if(recep==0){
         output_high (ESTADO);
         output_low (ERROR);
         output_low (RECEPCION);
      }
   }
}
```

Lo primero que hace es encender y apagar 3 veces todos los LEDs (solamente para saber que ya está listo para empezar )
Luego, si no hay ninguna interrupción se encienden los LEDs ESTADO y NO_INTERRUPCIÓN

Todo comienza cuando hay una interrupción externa en el PIC 2, se enciende el LED SERIAL y se envía un dato al PIC 1 dependiendo de un valor que va aumentando desde 0 hasta 20 para volver a empezar en 0 y seguir
Esto lo hace perfectamente

En el PIC 1 se debería activar la interrupción por recepción serial y activar el LED RECEPCIÓN y dependiendo de lo que reciba hay unas secuencias de LED para finalmente volver a dejar encendido solamente el LED ESTADO, cuando todo el proceso acabe.

Ahora bien, en simulación y en físico el PIC 2 funciona correctamente, sin ningún problema
El PIC 1 tiene dos problemas:
*Físico:*
No enciende nunca ningún LED y al comienzo debería encender los tres LED en la misma secuencia que el PIC 2
* No es problema del PIC porque le cargué el programa emisor y funciona perfectamente, el problema es con el programa receptor
*Simulación y Físico:*
No se cumple correctamente la secuencia que debería en los LEDs correspondientes


----------



## TRILO-BYTE (Jul 14, 2015)

estoy viendo otra marranada tuya 

eso me pasa por no leer completamente el codigo

estas usando *una interrupcion*

en una interrupcion se usa *la menor cantidad de codigo posible*

10 instrucciones en una interrupcion es demaciado y una barbaridad al meterle *DELAY * eso no se hace en una iterrupcion

lo que yo recomiendo es que en la interrupcion del RDA leas lo que llega nada mas unicamente leer

y en el main metes tus IF

y de hecho un switch es mas rapido que un if

ejemplo

char *valor; //variable global valor uso char para ahorrar memoria y no usar int "en caso de usar otro compilador"

interrupcion ()
{
gets(valor);  el apuntador lee toda la cadena que llega por RS232
} 

void main()

while(1) 
{
if( valor[1] == 21)
{
//secuencia
}

if( valor[2] == 45)
{
//secuencia2
}

if( valor[3] == 80)
{
//secuencia3
}

}

}


----------



## superdog13 (Jul 15, 2015)

Lo de la interrupción lo sé, pero en ese programa que no hace nada más y en el cual uno tiene control sobre la interrupción no es algo muy relevante, o sí ???


----------



## D@rkbytes (Jul 16, 2015)

No le veo sentido usar interrupciones, si dentro del servicio vas a entretener el programa con retardos.

Mejor usa polling y deja que las interrupciones puedan funcionar como lo que son.


----------



## TRILO-BYTE (Jul 16, 2015)

yo digo que meter delays de 5000 milisegundos , bucles while(1) y 50 instrucciones dentro de la interrupcion 

va a quedar bien chido


----------



## superdog13 (Jul 17, 2015)

Bueno, el ejemplo de la interrupción funcionó muy bien con estos dos códigos:

*Emisor*

```
#include <16f1827.h>
#use * * delay (internal = 32 MHz) * * * * // Fosc=32Mhz
#use * * RS232(UART1)

#define NO_INTERRUPCION * * * PIN_B4
#define EXTERNO * * * * * * * PIN_B5

void main(){
 * int c=0;
 * int e[21]={0x7E,0x00,0x11,0x90,0x00,0x00,0x01,0x03,0x0A,0x02,0x02,0x00,0xFF,0xFE,0x01,0x01,0x20,0x83,0x0B,0x01,0xB1};

 * enable_interrupts(int_ext);
 * ext_int_edge(L_TO_H);
 * enable_interrupts(GLOBAL);
 * 
 * output_high (EXTERNO);
 * output_high (NO_INTERRUPCION);
 * delay_ms(500);
 * output_low (EXTERNO);
 * output_low (NO_INTERRUPCION);
 * delay_ms(500);
 * output_high (EXTERNO);
 * output_high (NO_INTERRUPCION);
 * delay_ms(500);
 * output_low (EXTERNO);
 * output_low (NO_INTERRUPCION);
 * delay_ms(500);
 * output_high (EXTERNO);
 * output_high (NO_INTERRUPCION);
 * delay_ms(500);
 * output_low (EXTERNO);
 * output_low (NO_INTERRUPCION);
 * delay_ms(500);
 * 
 * while(TRUE){
 * * *output_high (NO_INTERRUPCION);
 * * *delay_ms(500);
 * * *output_low (NO_INTERRUPCION);
 * * *putc(e[c]);
 * * *output_high (EXTERNO);
 * * *delay_ms(1000);
 * * *output_low (EXTERNO);
 * * *c++;
 * * *if(c>20){
 * * * * c=0;
 * * * * output_high (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * * * output_low (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * * * output_high (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * * * output_low (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * * * output_high (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * * * output_low (NO_INTERRUPCION);
 * * * * delay_ms(500);
 * * *}
 * }
}
```

*Receptor*

```
#include <16f1827.h>
#use * * delay (internal = 32MHz) * * * * // Fosc=32Mhz
//#use * * delay (internal = 4MHz) * * * * *// Fosc=4Mhz, para simulación
#use * * RS232(UART1)

#define RECEPCION * * * PIN_B4
#define ERROR * * * * * PIN_B5
#define ESTADO * * * * *PIN_B6 

/*
ESTADO
-> CONSTANTE: DISPONIBILE
-> APAGADO: OCUPADO
-> 2 INT: TAM_TRAMA
-> 3 INT: COMPLETO
*/

int temp[32]={0};
int br=0;
int recep=0;
int pos;
int tamano=0;
int err=0;
int serial=0;
int tam=0;
int espera=0;
 
#int_RDA
void RDA_isr(void){
 * temp[br]=getc();
 * br=br+1;
 * if(br==1 && temp[0]!=0x7E){
 * * *br=0;
 * * *err=1;
 * }
 * if(br<3 || br>3){tam=0;}
 * if(br==3){
 * * *tam=1;
 * * *tamano=temp[2]+4;
 * }
 * if(br<tamano){espera=1;}
 * if(br==tamano){
 * * *for(pos=0;pos<=32;pos++){temp[pos]=0;}
 * * *br=0;
 * * *recep=1;
 * * *tamano=0;
 * }
 * serial=1;
}
 
void main(){
 * output_low (RECEPCION);
 * output_low (ERROR);
 * output_low (ESTADO);
 
 * enable_interrupts(int_rda);
 * enable_interrupts(GLOBAL);
 * 
 * output_high (RECEPCION);
 * output_high (ERROR);
 * output_high (ESTADO);
 * delay_ms(500);
 * output_low (RECEPCION);
 * output_low (ERROR);
 * output_low (ESTADO);
 * delay_ms(500);
 * output_high (RECEPCION);
 * output_high (ERROR);
 * output_high (ESTADO);
 * delay_ms(500);
 * output_low (RECEPCION);
 * output_low (ERROR);
 * output_low (ESTADO);
 * delay_ms(500);
 * output_high (RECEPCION);
 * output_high (ERROR);
 * output_high (ESTADO);
 * delay_ms(500);
 * output_low (RECEPCION);
 * output_low (ERROR);
 * output_low (ESTADO);
 * delay_ms(500);
 
 * while(TRUE){
 * * *if(err==1){
 * * * * err=0;
 * * * * output_low (ERROR);
 * * * * output_low (ESTADO);
 * * * * output_low (RECEPCION);
 * * * * output_high (ERROR);
 * * * * delay_ms(1000);
 * * * * output_low (ERROR);
 * * * * delay_ms(1000);
 * * * * output_high (ERROR);
 * * * * delay_ms(1000);
 * * * * output_low (ERROR);
 * * * * delay_ms(1000);
 * * *}
 * * *if(serial==1){
 * * * * output_low (ERROR);
 * * * * output_low (ESTADO);
 * * * * output_high (RECEPCION);
 * * * * if(tam==1){output_high (ESTADO);}
 * * * * if(espera==1){output_high (ERROR);}
 * * * * serial=0;
 * * * * delay_ms(1000);
 * * * * tam=0;
 * * * * espera=0;
 * * *}
 * * *if(recep==1){
 * * * * recep=0;
 * * * * output_low (ERROR);
 * * * * output_low (ESTADO);
 * * * * output_low (RECEPCION);
 * * * * output_high (ESTADO);
 * * * * delay_ms(500);
 * * * * output_low (ESTADO);
 * * * * delay_ms(500);
 * * * * output_high (ESTADO);
 * * * * delay_ms(500);
 * * * * output_low (ESTADO);
 * * * * delay_ms(500);
 * * * * output_high (ESTADO);
 * * * * delay_ms(500);
 * * * * output_low (ESTADO);
 * * * * delay_ms(500);
 * * *}
 * * *else if(recep==0){
 * * * * output_low (RECEPCION);
 * * * * output_low (ERROR);
 * * * * output_high (ESTADO);
 * * *}
 * }
}
```

View My Video






Ahora aún sigo teniendo problemas con el programa original

Así está en este momento:


```
#include <16F1827.h>
#device WRITE_EEPROM = NOINT
#FUSES WDT, NOPUT, PROTECT, NOMCLR, NOCLKOUT, NOCPD, NOBROWNOUT, PLL, INTRC_IO,
#use delay(clock=32M)
#use RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B1, stream=com,errors)

...

int temp[32]={0};
int br=0;
int recep=0;
int pos;
int tam_tram=0;
int temp2;
int tamano=0;

...

#int_RDA
void RDA_isr(void){
 * temp[br]=getc(com);
 * br=br+1;
 * if(br==1 && temp[0]!=0x7E){br=0;}
 * if(br==3){tamano=tam_tram=temp[2]+4;}
 * if(br==tamano){
 * * *recep=1;
 * * *br=0;
 * * *tamano=0;
 * }
}

...

void main (void){
 * //VARIABLES MAIN
 * //INICIO MODULOS GENERAL
...
 * //INICIO MODULO DIMMER
 * port_b_pullups(0b01010001);
 * setup_wdt(WDT_ON|WDT_2S);
...
 * RESTART_WDT();
 * if(...
 * * *//CONFIGURACION INTERRUPCIONES
 * * *ext_int_edge(L_TO_H);
 * * *setup_timer_0(T0_INTERNAL|T0_DIV_4);
 * * *enable_interrupts(global);
 * * *enable_interrupts(int_ext);
 * * *enable_interrupts(int_rda); * * * * // Interrupción comunicación serial
 * * *enable_interrupts(INT_TIMER0);
 * * *...
 * }

 * while(true){
 * * *RESTART_WDT();
 * * *// VALIDACIÓN DE RECEPCIÓN
 * * *if(recep==1){
 * * * * RESTART_WDT();
 * * * * for(pos=0;pos<=br-1;pos++){fun_1(pos,temp[pos]);}
 * * * * for(pos=0;pos<=32;pos++){temp[pos]=0;}
 * * * * temp2=fun_2();
 * * * * fun_3(temp2);
 * * * * temp2=0;
 * * * * recep=0;
 * * *}
...
 * }
}
```

Y en la librería está de esta forma:


```
...

void fun_1(int cn,int dato){
	brr[cn]=dato;
}

int fun_2(){
	int rx;
...
	rx=brr[0];
...
}
...
```

Ya está recibiendo datos, lo que sucede es que está haciendo algo que no debería

La función principal del código global es encender o apagar un bombillo de varias formas o a varios niveles (un dimmer)
La prueba la estoy haciendo con dos comandos básicos: encender o apagar
Cualquiera de los dos apaga el LED y lo enciende por algo menos de medio segundo
Solamente hace eso y no lo hace siempre, solo tras varios envíos del comando

No se si puede estar fallando a la hora de hacer la recepción o qué puede ser


----------

