Que tal amigos del foro, bueno como dice el título el tema se trata del uso eficiente de mas de dos puertos seriales en un solo PIC el cual obviamente tiene un solo puerto serial físico.
El punto es que mientras que usando el puerto físico no tengo ningún problema, la situación se malogra cuando declaro un nuevo puerto serie pues en el momento en el que simulo el programa con ISIS, la interrupción del puerto serie deja de funcionar y deja a mi programa en el aire sin hacer lo que deseo.
Aqui les explico un poco mas sobre el código.
Primero: Mi programa tiene un programa principal y otros secundarios, el que les pongo aqui es un "source code" secundario llamado "serial llave"
La parte mas importante es el del #INT_RDA ya que lo que sigue después de eso es la interrupción generada cuando un dato serial llega al puerto del PIC.
En el codigo ".h" de mi aplicación tengo la declaración del puerto serie
Como verán estoy usando el pic 16f876a y los pines del puerto serial son los del puerto serial físico del micro.
Si el programa lo dejo alli todo funciona de maravilla, cuando llega un dato al puerto serie pues se genera la interrupción y el programa hace lo que debe hacer.
El problema es que yo necesito usar dos puertos seriales, 1 el de los pines del puerto físico y 2 un puerto serial con las siguientes características:
#use rs232(baud=9600,parity=N,xmit=PIN_C3,rcv=PIN_C4,bits=8,stream=RS_485)
pero cuando hago esa declaración, deja de funcionar todo, ya no se genera la interrupción por entrada al puerto serial y el programa no hace lo que quiero.
y el código del uso del otro puerto serial es el siguiente:
Finalmente el mi "source code" principal llamo a las dos verificaciones de los puertos de la siguiente manera:
La pregunta es si ¿alguien de ustedes tiene alguna experiencia positiva al usar mas de 1 puerto serial con un pic? o si me puede indicar como mejorar mi código para no tener problemas con la lectura de los dos puertos?
El punto es que mientras que usando el puerto físico no tengo ningún problema, la situación se malogra cuando declaro un nuevo puerto serie pues en el momento en el que simulo el programa con ISIS, la interrupción del puerto serie deja de funcionar y deja a mi programa en el aire sin hacer lo que deseo.
Aqui les explico un poco mas sobre el código.
Primero: Mi programa tiene un programa principal y otros secundarios, el que les pongo aqui es un "source code" secundario llamado "serial llave"
Código:
struct
{
int8 address_rsp; //direccion del que envia el mensaje
int8 len; //numero de bytes en el mensaje recivido
int8 data[20];
}S_Llave_rx;
int8 PLlave; //Puertos seriales, indica si esta libre, lleno u ocupado
int Llave_ind_trama=0;
char Llave_x_char;
int1 Llave_New_trama=0; //Se pone a 1 cuando se ha terminado de recibir la trama
int Llave_step_trama=255;
int Llave_cks1=0xAA;
int Llave_tx_data[20];
int Llave_Bus_Act;
#int_RDA
void RDA_isr(void)
{
Llave_x_char=fgetc(S_Llave);
//x_char=getc();
if(Llave_BUS_ACT==1)
{ Llave_BUS_ACT=0;}
if(Llave_x_char=='#'&& Llave_step_trama==0xFF)
{ Llave_step_trama=0;
Llave_New_trama=0;
Llave_ind_trama=0;
Llave_cks1=0xAA;
PLlave=Ocupado;
}
if(Llave_step_trama!=0xFF)
{
switch(Llave_step_trama)
{ case 0x00: //para el #
++Llave_step_trama;
break;
case 0x01: ++Llave_step_trama;
if(Llave_x_char!=Puerto_LCD)
{ Llave_step_trama=0xFF;} //abandonar por que no coincide con el ID de este RTU
break;
case 0x02: ++Llave_step_trama;
S_Llave_rx.address_rsp=Llave_x_char; //guardar el ID del que envia
break;
case 0x03: ++Llave_step_trama;
S_Llave_rx.len=Llave_x_char;
break;
default: if(Llave_ind_trama<S_Llave_rx.len)
{
S_Llave_rx.data[Llave_ind_trama]=Llave_x_char;
Llave_cks1^=Llave_x_char;
}
if(Llave_ind_trama==S_Llave_rx.len)
{
if(Llave_x_char==Llave_cks1)
{
Llave_New_trama=1;
S_Llave_rx.data[Llave_ind_trama]='\0';
}
Llave_step_trama=0xFF;
}
++Llave_ind_trama;
break;
}
}
}
int Verifica_PSerie()
{
if(Llave_new_trama==1)
{
Llave_new_trama=0;
PLlave=Lleno;
return 1;
}
else
{
Llave_new_trama=0;
PLlave=Libre;
return 0;
}
}
En el codigo ".h" de mi aplicación tengo la declaración del puerto serie
Código:
#include <16F876A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=S_Llave)
Si el programa lo dejo alli todo funciona de maravilla, cuando llega un dato al puerto serie pues se genera la interrupción y el programa hace lo que debe hacer.
El problema es que yo necesito usar dos puertos seriales, 1 el de los pines del puerto físico y 2 un puerto serial con las siguientes características:
#use rs232(baud=9600,parity=N,xmit=PIN_C3,rcv=PIN_C4,bits=8,stream=RS_485)
pero cuando hago esa declaración, deja de funcionar todo, ya no se genera la interrupción por entrada al puerto serial y el programa no hace lo que quiero.
y el código del uso del otro puerto serial es el siguiente:
Código:
struct
{
int8 address_rsp; //direccion del que envia el mensaje
int8 len; //number de bytes en el mensaje recivido
int8 data[20]; //data of the message received
}RS_485_rx;
int RS_485_ind_trama=0;
int RS_485_x_char;
int1 RS_485_New_trama=0; //Se pone a 1 cuando se ha terminado de recibir la trama
int RS_485_step_trama=255;
int RS_485_cks1=0xAA;
int RS_485_tx_data[20];
int RS_485_Bus_Act;
void RS_485_RDA_isr()
{
RS_485_x_char=fgetc(RS_485);
if((RS_485_x_char>0) && (RS_485_BUS_ACT==1))
{ RS_485_BUS_ACT=0; }
if((RS_485_x_char=='#') && (RS_485_step_trama==0xFF)) //#=35
{
RS_485_step_trama=0;
RS_485_New_trama=0;
RS_485_ind_trama=0;
RS_485_cks1=0xAA;
}
if(RS_485_step_trama!=0xFF)
{
switch(RS_485_step_trama)
{
case 0x00: //para el #
++RS_485_step_trama;
break;
case 0x01: ++RS_485_step_trama;
if(RS_485_x_char!=Puerto_LCD)
{ RS_485_step_trama=0xFF;} //abandonar por que no coincide con el ID de este RTU
break;
case 0x02: ++RS_485_step_trama;
Rs_485_rx.address_rsp=RS_485_x_char; //guardar el ID del que envia
break;
case 0x03: ++RS_485_step_trama;
Rs_485_rx.len=RS_485_x_char;
break;
default: if(RS_485_ind_trama<Rs_485_rx.len)
{
Rs_485_rx.data[Rs_485_ind_trama]=RS_485_x_char;
RS_485_cks1^=RS_485_x_char;
}
if(RS_485_ind_trama==Rs_485_rx.len)
{
if(RS_485_x_char==RS_485_cks1)
{
RS_485_New_trama=1;
Rs_485_rx.data[RS_485_ind_trama]='\0';
}
RS_485_step_trama=0xFF;
}
++RS_485_ind_trama;
break;
}
}
}
int Verifica_RS_485()
{
RS_485_RDA_isr();
if(RS_485_New_trama==1)
{
RS_485_New_trama=0;
return 1;
}
else
{
RS_485_New_trama=0;
return 0;
}
}
Código:
if(Verifica_PSerie()==1) //Detecta si se hay datos en el puerto serie 1
{
Com_Puerto=Puerto_Llave;
}
else if(Verifica_RS_485()==1)
{
Com_Puerto=Puerto_RS485;
}
else
{
Com_Puerto=Ninguno;
}