Error en interrupción y mensajes en puerto COM CCS

Hola a todos, disculpen el titulo del mensaje, no supe como expresarlo, espero que puedan ayudarme en este problema, estoy tratando de comunicar un pic con la pc via serial.
1. En la pc hice un pequeño script en python para enviar datos por el puerto com, en el pic estoy usando CCS,
2. El objetivo es enviar un msj al pic y que pueda cambiar el estado del pin_c0 cada vez que reciba un mensaje (no debe cambiar de estado por dato, sino por msj) para esto se configura un timer de .01ms de modo que, tras cada dato recibido se activa el temporizador, si se desborda el temporizador se entiende que el msj a finalizado y se procede a cambiar el estado del pin_c0.

3. El programa funcion correctamente cuando el mensaje es menor de 5 bytes.

El problema viene cuando se envian al menos 5 bytes en un msj, cuando esto ocurre el pin_c0 cambia su estado 2 veces, apenas se percibe que ha cambiado el estado. Pareciera que al leer el 4byte se desborda el temporizador y se produce el cambio de estado en pin_c0, pero ¿Como puede ser posiblbe si se restablece el timer0 en #int_rda??

script en python para enviar msj al puerto com

Python:
import serial
import time
ser = serial.Serial("COM3", 9600, timeout=1)
msj= bytes([0x01, 0x04, 0x00, 0x15, 0x00])
print(msj)
print("Esperando:")
while(1):
    if (input("continuar: ")=='s'):
        ser.write(msj)
    else:
        break
exit(1)


codigo del pic

C:
#include <18F458.h>

#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES HS

#use delay(crystal=20MHz)

#use rs232(baud=MODBUS_BAUD,  xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS, ENABLE=PIN_C5, disable_ints, timeout=10)

#define TIME0 60

int8 buffer[64];
int8 index=0;//usado como  indice para recorrer el buffer

#int_rda
void serial_isr() {
   disable_interrupts(int_timer0);
   buffer[index++] =  getchar();
   set_timer0(TIME0);
   enable_interrupts(int_timer0);
}


#int_timer0
void timeout_isr(){
   disable_interrupts(int_timer0);
   output_toggle(pin_c0);
   index=0;
  
}

void main()
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT );
   disable_interrupts(INT_TIMER0);
   set_timer0(TIME0); // configurado a 0.01s
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   while(true);
}
 

D@rkbytes

Moderador
Si declaras esto se está implementando RS-232 por software:
#use rs232(baud=MODBUS_BAUD, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS, ENABLE=PIN_C5, disable_ints, timeout=10)

¿Por qué? Porque le estás diciendo al compilador los pines que se deben usar para Tx y Rx y eso hará que se use RS-232 por software y no por hardware.
Lo correcto para usar el módulo USART sería así:
#use rs232 (UART1, BAUD = Los_Baudios) // N, 8, 1 son valores por defecto.

El resto de configuraciones que agregaste las veo innecesarias para lo que requieres hacer.

El problema viene cuando se envían al menos 5 bytes en un mensaje, cuando esto ocurre el pin_c0 cambia su estado 2 veces, apenas se percibe que ha cambiado el estado.
Pareciera que al leer el 4 bytes se desborda el temporizador y se produce el cambio de estado en pin_c0, pero ¿Cómo puede ser posiblbe si se restablece el timer0 en #int_rda??
Podría ser por tanta configuración innecesaria que has usado.
 
Justo iba a poner algo similar.
Estás temporizando la comunicación y te olvidas que es asincronica, eso quiere decir que no tiene una señal de clock/reloj del cual fiarse el tiempo que tarda. Por el contrario, lee los datos hasta algun \n o \r o ambos.

Por otro lado, lee las normas, "msj" significa "eme ese jota", y no "mensaje"
 
Probé usando esta configuracion #use rs232(baud=MODBUS_BAUD, UART1) y se activa dos veces la interrupcion del temporizador. Como me daba el mismo problema, cambié los baudios a 19200 y puedo leer 6 bytes sin problemas, como un solo mensaje, ahora se repite el problema en el septimo byte. Saben como puedo solucionarlo?
 

D@rkbytes

Moderador
No sé cuál sea el valor de MODBUS_BAUD porque no está declarado, sin embargo, no es importante, siempre y cuando tanto el emisor como el receptor tengan el mismo baudrate.
Si quieres recibir una cadena completa tan solo debes usar gets(buffer);

Por ejemplo:
C:
#INT_RDA
void sdi_rx_usart (void)
{
    gets(buffer);
}
 
Estoy tratando de trabajar algo propio con modbus rtu, otra cosa me estoy percatando que cada vez que transmito un dato se activa int_rda, me parece que debe ocurrir cuando recibo no cuando transmito. Saben que pueda ser?
 
Código:
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES HS

#use delay(crystal=20MHz)

#use rs232(baud=MODBUS_BAUD,  xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS, ENABLE=PIN_C5, disable_ints, timeout=10)

#define TIME0 60

int8 buffer[64];
int8 index=0;//usado como  indice para recorrer el buffer
int8 enviar=0;

#int_rda
void serial_isr() {
   disable_interrupts(int_timer0);
   buffer[index++] =  getchar();
   set_timer0(TIME0);
   enable_interrupts(int_timer0);
}


#int_timer0
void timeout_isr(){
   disable_interrupts(int_timer0);
   output_toggle(pin_c0);
   index=0;
   enviar=1;
 
}

void main()
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT );
   disable_interrupts(INT_TIMER0);
   set_timer0(TIME0); // configurado a 0.01s
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   while(true){
       if (enviar){
        putchar(0x01);
        enviar = 0;
    }
    }
   }
}

el pic queda enviando 0x01
 

D@rkbytes

Moderador
No hiciste caso sobre lo que comenté, sigues usando RS-232 por software.
Si no pones atención a lo que se te recomienda, nunca vas a aprender.
 
ya lo habia modificado como dijiste y no me resultó, estaba probando con esa configuración a ver si obtenia algo distinto. de igual manera se sigue activando int_rda cuando transmito
 
No creo que sea util gets() porque al final terminare recibiendo una trama modbus rtu, logre solucionar lo de la interrupcion, era un detalle en la alta impedacia del max485 que estaba usando. La cantidad de bytes que recibo por he logrado solucionarla aumentado la velocidad del rs232 sin embargo sigo sin compreder la razón. Gracias por el tiempo dedicado.
 

D@rkbytes

Moderador
Nunca he implementado el protocolo modbus pero al parecer no tiene nada que ver con lo que estás haciendo.
De cualquier forma, en la carpeta de ejemplos de PIC C Compiler vienen dos ejemplos.
ex_modbus_master.c y ex_modbus_slave.c
 
Arriba