Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola Señores, tengo un problema y pregunto sobre este tema por si me podéis echar un cable con alguna sugerencia.
Resulta que tengo un PIC 16F876a que me controla unos motores mediantes relés y a su vez el PIC es controlado por un PC mediante una comunicación serie, el problema que tengo es que tras varias transmisiones entre PIC y PC, parece que el PIC pierde el norte y no contesta más....
Para que os hagáis una idea, desde el PC siempre transmito 3 bytes con los comandos, y siempre espero 2 bytes de respuesta del PIC que informan de la operación realizada, algunos comandos implican retardos, pero estos retardos se realizan posteriormente a contestar al PC por parte del PIC, y antes de volver a enviarle una orden al PIC me espero un ratito... el caso es que tras varias transmisiones ya no recibo nada del PIC.
Hay que tener en cuenta que uso una rutina enganchada al Timer0, para que el PIC haga otras tareas referentes a los fines de carrera de los motores.
He probado en comunicarme mediante puerto serie, con la aplicación que tengo desarrollada en C, como mediante con el Hyperterminal y en los dos casos sucede lo mismo, el PIC parece no seguir contestando, lo curioso es que a veces sucede antes y otras veces despues.
Alguna idea de porque, pues necesito controlar el PIC desde el PC y ya descarte i2c pues también tenía problemas.
Ciao y gracias.
Si vamos a ver la alimentación es compartida por dos motores de coche, conectados a relés, transistores, optoacopladores y un chorrón de condensadores.
A la entrada de tensión tiera del circuito se han metido varios condensadores para filtrar un poco... y las salidas del PIC que van a los motores pasan antes por optoacopladores, de los opto pasan a relés y con los relés controlamos dos motores.
Puede ser problema, esto?
Y si mientras hay sincronización se devolvía todo correctamente.Entiendo que con esto quieres decir que la rutina que te puse funciona bien ¿ correcto ? ó ¿ te refieres a que ya no tienes el problema?
[...]Gracias por intentar ayudarme!! :wink:De nada.
Una pregunta más:
Si la rutina de interrupción para recoger el dato serie es llamada cada vez que llegan datos serie por el PIN C7 (según tu definición "use rs232"), ¿por qué utilizas kbhit() dentro de la rutina de interrupción ?...A lo mejor me he perdido algo en toda la ristra de mensajes, y estoy preguntando una tontería...
No preguntas tonterias Sphinx, más bien las tonterías las peudo decir yo que soy el "Iniciado".
La comunicación sigue funcionando no muy bien, la rutina que tu me pegaste basicamente es la misma que yo uso, tanto si en eco como con el el funcionamiento es el mismo, al tiempo se desincroniza.
Sobre lo del kbhit lo utilizo porque lo he visto así en casi todos los ejemplos, aunque probablemente tengas razón en lo que comentas, de todos modos viendo como trabaja el kbhit, tampoco debe ser problema el que esté no?
Hemos intentando filtrar bastante todo lo referente a ruido, de ahí el uso de optoacopladores para manejar los relés y los condensadores para la alimentación del pic, etc.
Bueno tengo nuevas conclusiones a la vista de los ultimos cambios que le he aplicado al programa....
int contador=0;
#INT_RTCC
void RutinaReset()
{
disable_interrupts(int_RTCC);
contador++;
if (contador==15) {
output_high(LED_STOP);
index=0;
} else {
set_timer0(0);
enable_interrupts(int_RTCC);
}
}
#INT_RDA
void serial_interrupt()
{
disable_interrupts(INT_RDA);
// Hacemos un reset del WDT para que no se cuelgue
restart_wdt();
if (kbhit()) {
if (index==0) {
output_low(LED_STOP);
input_ready=FALSE;
comando=getc();
putc(comando);
contador=0;
// activamos el temporizador
SET_TIMER0(0);
// Para activarlo haremos:
enable_interrupts(int_RTCC);
index++;
} else if (index==1) {
dato1=0x00;
dato1=getc();
putc(dato1);
index++;
} else if (index==2) {
// Recibimos el tercer byte luego desactivamos el temporizador
disable_interrupts(int_RTCC);
dato2=getc();
putc(dato2);
input_ready=TRUE;
output_toggle(LED_AZUL);
index=0;
}
}
enable_interrupts(INT_RDA);
}
Basicamente he metido un temporizador, cuando se recibe el primer byte de la trama de 3 bytes, se activa con un 1s de duración, si en ese segundo no se ha recibido el tercer byte, se resetea la trama para interpretar que lo proximo que se reciba será el primer byte.
Yo en main:
while (1) {
restart_wdt();
if (input_ready) {
// Para que no se resetee el PIC
// procesamos
switch(comando) {
case INIT: StopMotores();
printf("ix");
break;
case CONSULTA_MOTOR1:
printf("c%c", estado_motor1);
break;
case CONSULTA_MOTOR2:
printf("c%c", estado_motor2);
break;
...
Por cada trama recibida correctamente hago siempre algo y devuelvo 2 bytes con cierto resultado...
Pues bien teniendo en cuenta todo lo anterior, compruebo que envío los tres bytes correctamente, pues se enciden el LED_AZUL y no el rojo, pero no recibo ni los dos bytes, ni se mueve los motores....
En el PC las rutinas de recepción me dan fallo de que no se recibe nada, lo curioso es que el eco de los tres bytes que envio del PC al PIC (es decir la trama con el comando y datos) si se recibe bien, pero la respuesta a ese comando no se recibe.
Puede ser que la parte del main se encuentre colgada?
Ciao y gracias.
Curiosamente acabo de ejecutar lo anterior de nuevo, el proceso se ha ejecutado correctamente durante un tiempo importante, y se ha quedado en un estado que cuando he abierto el hyperterminal la pantalla se llenaba de basura, e incluso la luz azul no paraba de parpadear como loca como si le estuviera enviando datos (es lo que debe suceder cuando recibe tres bytes) pero nadie le estaba enviando nada...
Ya esto me deja flaseado!!! Alguna sugerencia?