Aqui te paso el programa, bueno no lo he modificado, es tal como lo estoy usando, lo unico que havria que quitarle en la interrupcion por puerto serial seria el pin que uso para rs485, por lo demas esta correcto, hay 4 puertos virtuales, y uno que recepciona de la PC, cualquier pregunta, haganmela, aqui lo pongo, ya que no lo puedo subir como adjunto, sale que no hay espacio
/*--------------------------------------------------------------------------------------
Funciones para recepcionar o enviar tramas
--------------------------------------------------------------------------------------
----------------------------
TRAMAS MAESTRO / ESCLAVOS:
----------------------------
Trama de transmision a los canales RS232-A a RS232-C:
*------------------------------------*
|SOH|STX|ENQ|RS|D1|D0|ETX|CHECKSUM|CR|
*------------------------------------*
Trama de recepcion de los RS232-A a RS232-C. Es la misma para la PC. La diferencia es
que los PIC D1 y D0 van de 00 a 16. En el caso de PC es de 00 a 47.
*--------------------------------------*
|SOH|STX|D1|D0|RS|C|D|U|ETX|CHECKSUM|CR|
*--------------------------------------*
Trama de comando que envia la el maestro a un esclavo indicando un PUERTO, una LINEA y
el valor que puede tener la misma (0 ó 1)
*-----------------------------------------------------*
|SOH|STX|DC1|RS|PORT|RS|LINEA|RS|VALOR|ETX|CHECKSUM|CR|
*-----------------------------------------------------*
----------------------
TRAMAS PC / MAESTRO:
----------------------
Trama que envia la PC para solicitar algun dato del buffer de los esclavos. Similar
al comando que se emplea para solicitar los datos a los esclavos desde el maestro.
*------------------------------------*
|SOH|STX|ENQ|RS|D1|D0|ETX|CHECKSUM|CR|
*------------------------------------*
Trama de comando que envia la PC al maestro indicando en el campo CANAL el destinatario
*--------------------------------------------------------*
|SOH|STX|DC1|CANAL|PORT|RS|LINEA|RS|VALOR|ETX|CHECKSUM|CR|
*--------------------------------------------------------*
Caracteres de control. Tabla de codigos ASCII
SOH - Comienzo de encabezamiento
STX - Comienzo de texto
D1 - Indicador de decenas del buffer
D0 - Indicador de unnidades del buffer
ETX - Final de texto
ENQ - Pregunta
Checksum - Suma en 8 bits de los valores anteriores
CR - Retorno de carro
RS - Separador de registros
C - Centenas
D - Decenas
U - Unidades
CANAL- Canal al cual se envia un comando desde la PC
/*------------------------------------------------------------------------------------
Definiciones y declaraciones
-----------------------------------------------------------------------------------*/
#define SOH 0x01 // Definicion de los caracteres. Tabla de codigo ASCII
#define STX 0x02
#define ETX 0x03
#define CR 0x0D
#define LF 0x0A
#define RS 0x1E
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define ENQ 0x05
#define DC1 0x11
//-------------------------------------------------------------------------------------
#define MAX_BUFFER 10 // Buffer para los datos de los esclavos
static char buffer[MAX_BUFFER*3];
//-------------------------------------------------------------------------------------
#define MAX_RX 11 // Buffer de recepcion. 11 posiciones
static char buffer_rx[MAX_RX];
static int ptro_buffer_rx=0; // Ptro a la sgte posicion que esta vacia
//-------------------------------------------------------------------------------------
#define MAX_PREGUNTA 9 // Nro caracteres de la pregunta de la PC
#define MAX_CONTROL1 12 // Nro caracteres del comando a un esclavo
#define MAX_USART 12 // Buffer para Rx del Usart
static char buffer_usart[MAX_USART];
static int ptro_buffer_usart=0; // Ptro a la sgte posicion que esta vacia
//-------------------------------------------------------------------------------------
char truefalse;
#bit flag =truefalse.0 // Bandera de tx/rx en canales
#bit tx_comando =truefalse.1 // Indica si hay comando disponible en un canal
#bit timeout_error =truefalse.2 // timeout en la lectura de un canal
char canal_comando; // Indica a que canal se va a eniar un comando
//-------------------------------------------------------------------------------------
#bit BIT_RS232A=PORTD.7 // Led indicador de actividad en el canal: RS232-A
#bit BIT_RS232B=PORTD.6 // RS232-B
#bit BIT_RS232C=PORTD.5 // RS232-C
#bit BIT_RS232D=PORTD.4 // RS232-D, canal para transmitir los valores a la PC
/*-------------------------------------------------------------------------------------
INTERRUPCION SERIAL
-------------------------------------------------------------------------------------*/
#byte SPBRG_C=SPBRG // Definicion de los registros que controlan el USART
#byte TXREG_C=TXREG
#byte RCREG_C=RCREG
#bit BRGH_C =TXSTA.BRGH // Definicion de los bits. Registros Tx/Rx
#bit SYNC_C =TXSTA.SYNC
#bit TXEN_C =TXSTA.TXEN
#bit TX9_C =TXSTA.TX9
#bit RX9_C =RCSTA.RX9
#bit CREN_C =RCSTA.CREN
#bit SPEN_C =RCSTA.SPEN
#bit TXIF_C =PIR1.TXIF // Definicion de flag de Tx/Rx
#bit RCIF_C =PIR1.RCIF
#bit OERR_C =RCSTA.OERR // Definicion de los bits de estado del USART en Rx
#bit FERR_C =RCSTA.FERR
/*-------------------------------------------------------------------------------------
FUNCIONES
-------------------------------------------------------------------------------------*/
// Rutina para la recepcion serial por interrupcion
static int dir_int; // Convierte de ASCII a Nro. Dir de buffer a enviar
static char centenas_int; // Centenas, decenas y unidades del dato a Tx
static char decenas_int;
static char unidades_int;
#int_rda
rda_isr()
{
// Recepcion de valores via interrupcion que son almacenados en buffer_usart
if(ptro_buffer_usart < MAX_USART){
if(!OERR_C && !FERR_C ){ // Revisa los bits de errores
if( RCREG_C == EOT) ptro_buffer_usart=0;
else
buffer_usart[ptro_buffer_usart++]=RCREG_C;
}
else{ // Control de errores en USART
CREN_C = 0; // Reset OERR
CREN_C = 1;
dir_int = RCREG_C; // Reset del FERR
ptro_buffer_usart=0; // Reset del buffer del usart
}
}
else
ptro_buffer_usart=0;
// Verifica si tiene un mensaje de la PC tipo pregunta
if(buffer_usart[2] == ENQ && ptro_buffer_usart == MAX_PREGUNTA){
// Verifica checksum de la trama
if(buffer_usart[0]+buffer_usart[1]+buffer_usart[2]+buffer_usart[3]+
buffer_usart[4]+buffer_usart[5]+buffer_usart[6]==buffer_usart[7]){
dir_int=( buffer_usart[4]-"0" ) * 10 + ( buffer_usart[5]-"0" );
// Pasa a texto el contenido de buffer[dir]
centenas_int = (buffer[dir_int] / 100)+"0";
decenas_int = buffer[dir_int] % 100;
unidades_int = (decenas_int % 10) +"0";
decenas_int = (decenas_int / 10) +"0";
// Envio del mensaje a la PC
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ENABLE=PIN_C5)
putc(SOH) ;delay_ms(2);
putc(STX) ;delay_ms(2);
printf("%02u",dir_int) ;delay_ms(2);
putc(RS) ;delay_ms(2);
printf("%03u",buffer[dir_int]) ;delay_ms(2);
putc(ETX) ;delay_ms(2);
putc(SOH+STX+buffer_usart[4]+
buffer_usart[5]+
RS+centenas_int+decenas_int+
unidades_int+ETX)
;delay_ms(2);
putc(CR); ;delay_ms(2);
// Hace cambio en el led indicador
BIT_RS232D=0;delay_ms(100);BIT_RS232D=1;delay_ms(100);BIT_RS232D=0;
}
ptro_buffer_usart=0; // Reset del buffer del USART
}
// Verifica si tiene un mensaje de la PC tipo pregunta
if(buffer_usart[2] == DC1 && ptro_buffer_usart == MAX_CONTROL1){
// Verifica checksum de llegada
if(buffer_usart[0]+buffer_usart[1]+buffer_usart[2]+buffer_usart[3]+
buffer_usart[4]+buffer_usart[5]+buffer_usart[6]+buffer_usart[7]+
buffer_usart[8]+buffer_usart[9]==buffer_usart[10]){
if(buffer_usart[3]=="A") canal_comando=1; // Elije el canal
if(buffer_usart[3]=="B") canal_comando=2;
if(buffer_usart[3]=="C") canal_comando=3;
buffer_usart[3]=RS; // Prepara trama que va a enviar al canal
buffer_usart[10]=buffer_usart[0]+buffer_usart[1]+buffer_usart[2]+
buffer_usart[3]+buffer_usart[4]+buffer_usart[5]+
buffer_usart[6]+buffer_usart[7]+buffer_usart[8]+
buffer_usart[9];
tx_comando=TRUE; // Indica en el bucle principal que hay
// mensaje. Esto para evitar colisiones
// en los accesos concurrentes
// Hace cambio en el led indicador
BIT_RS232D=0;delay_ms(100);BIT_RS232D=1;delay_ms(100);BIT_RS232D=0;
}
ptro_buffer_usart=0; // Reset del buffer del USART
}
}
void configurar_usart()
{
BRGH_C = 1; // 9600 para un XTAL de 4MHz
SPBRG_C = 25;
SYNC_C = 0; // Configuracion del TXSTA y RCSTA
SPEN_C = 1; // Habilita pines de salida del USART
TX9_C = 0; // 8 bits de datos en Tx
TXEN_C = 1; // Habilita la transmision
RX9_C = 0; // 8 bits de datos en Rx
CREN_C = 1; // Recepcion continua
}
/*-------------------------------------------------------------------------------------
FUNCIONES
-------------------------------------------------------------------------------------*/
static int canal=0,posicion=0;
void valida_rs232()
{
if(ptro_buffer_rx >= MAX_RX){ // Si hay mensaje completo
// Calculamos el checksum de los datos que han llegado
if(buffer_rx[0]+buffer_rx[1]+buffer_rx[2]+
buffer_rx[3]+buffer_rx[4]+buffer_rx[5]+
buffer_rx[6]+buffer_rx[7]+buffer_rx[8]==buffer_rx[9])
buffer[canal*MAX_BUFFER+posicion]=(buffer_rx[5]-"0")*100+
(buffer_rx[6]-"0")*10+buffer_rx[7]-"0";
}
}
static unsigned long timeout; // Varibles para generar el timeout de un mensaje
int solicita_dato()
{
ptro_buffer_rx=0; // Inicializa valores y calcula checksum
timeout_error=FALSE;
timeout=0;
if(canal==0){
#use rs232(baud=9600,xmit=PIN_B3,rcv=PIN_B2) // RS232-A
BIT_RS232A=0; // Led que indica Tx
putc(EOT); delay_ms(2);
putc(SOH); delay_ms(2);
putc(STX); delay_ms(2);
putc(ENQ); delay_ms(2);
putc(RS); delay_ms(2);
putc(posicion / 10+"0");delay_ms(2);
putc(posicion % 10+"0");delay_ms(2);
putc(ETX); delay_ms(2);
putc(SOH+STX+ENQ+RS+ (posicion / 10+"0") + (posicion % 10+"0") +ETX);
delay_ms(2);
putc(CR);
do{
while(!kbhit()&&(++timeout<50000)) delay_us(10);// Espera rpta con timeout
if(kbhit()) buffer_rx[ptro_buffer_rx++]=getc();
else timeout_error=TRUE;
if(ptro_buffer_rx >= MAX_RX || timeout_error == TRUE)break;
}while(1);
if(timeout_error == FALSE) BIT_RS232A=1; // Led que indica Tx
}
if(canal==1){
#use rs232(baud=9600,xmit=PIN_B4,rcv=PIN_B5) // RS232-B
BIT_RS232B=0;
putc(EOT); delay_ms(2);
putc(SOH); delay_ms(2);
putc(STX); delay_ms(2);
putc(ENQ); delay_ms(2);
putc(RS); delay_ms(2);
putc(posicion / 10+"0");delay_ms(2);
putc(posicion % 10+"0");delay_ms(2);
putc(ETX); delay_ms(2);
putc(SOH+STX+ENQ+RS+ (posicion / 10+"0") + (posicion % 10+"0") +ETX);
delay_ms(2);
putc(CR);
do{
while(!kbhit()&&(++timeout<50000))delay_us(10); // Espera rpta con timeout
if(kbhit()) buffer_rx[ptro_buffer_rx++]=getc();
else timeout_error=TRUE;
if(ptro_buffer_rx >= MAX_RX || timeout_error == TRUE)break;
}while(1);
if(timeout_error == FALSE) BIT_RS232B=1;
}
if(canal==2){
#use rs232(baud=9600,xmit=PIN_D3,rcv=PIN_D2) // RS323-C
BIT_RS232C=0;
putc(EOT); delay_ms(2);
putc(SOH); delay_ms(2);
putc(STX); delay_ms(2);
putc(ENQ); delay_ms(2);
putc(RS); delay_ms(2);
putc(posicion / 10+"0");delay_ms(2);
putc(posicion % 10+"0");delay_ms(2);
putc(ETX); delay_ms(2);
putc(SOH+STX+ENQ+RS+ (posicion / 10+"0") + (posicion % 10+"0") +ETX);
delay_ms(2);
putc(CR);
do{
while(!kbhit()&&(++timeout<50000))delay_us(10); // Espera rpta con timeout
if(kbhit()) buffer_rx[ptro_buffer_rx++]=getc();
else timeout_error=TRUE;
if(ptro_buffer_rx >= MAX_RX || timeout_error == TRUE)break;
}while(1);
if(timeout_error == FALSE) BIT_RS232C=1;
}
if(timeout_error == TRUE || ptro_buffer_rx < MAX_RX) return 1;
delay_ms(10);
return 0;
}
/*--------------------------------------------------------------------------------------
Fin de la libreria
--------------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------------
Funcion principal
--------------------------------------------------------------------------------------*/
#zero_ram
void main()
{
set_tris_a(0x00); // Configura los puertos
set_tris_b(0x24);
set_tris_c(0x80);
set_tris_d(0x04);
set_tris_e(0x00);
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ENABLE=PIN_C5)
putc(SOH);
delay_ms(2); // Envia un caracter para indicar que el equipo esta operativo
configurar_usart(); // Configura el usart
enable_interrupts(INT_RDA); // Habilita la interrupcion del Rx Serial
enable_interrupts(global); // Habilita el GIE
tx_comando=FALSE;
do{
// Lectura de los valores que estan en los esclavos
flag=FALSE;
for(posicion=0;posicion<MAX_BUFFER;posicion++){
flag = solicita_dato();
if(flag==FALSE) valida_rs232();
else
for(posicion=0;posicion<MAX_BUFFER;posicion++)
buffer[canal*MAX_BUFFER+posicion]=0x00;
}
canal++; // Representa el cambio de canal que leemos (0,1,2)
if(canal==3) canal=0;
if(tx_comando==TRUE){ // Si hay comando para transmitir
if(canal_comando==1){
#use rs232(baud=9600,xmit=PIN_B3,rcv=PIN_B2) // RS232-A
putc(EOT);
delay_ms(2);
for(posicion=0;posicion<MAX_CONTROL1;posicion++){
putc(buffer_usart[posicion]);
delay_ms(2);
}
putc(EOT);
delay_ms(2);
}
if(canal_comando==2){
#use rs232(baud=9600,xmit=PIN_B4,rcv=PIN_B5) // RS232-B
putc(EOT);
delay_ms(2);
for(posicion=0;posicion<MAX_CONTROL1;posicion++){
putc(buffer_usart[posicion]);
delay_ms(2);
}
putc(EOT);
delay_ms(2);
}
if(canal_comando==3){
#use rs232(baud=9600,xmit=PIN_D3,rcv=PIN_D2) // RS323-C
putc(EOT);
delay_ms(2);
for(posicion=0;posicion<MAX_CONTROL1;posicion++){
putc(buffer_usart[posicion]);
delay_ms(2);
}
putc(EOT);
delay_ms(2);
}
tx_comando=FALSE; // Resetea bandera de transmision de comando
}
}while(TRUE);
}