Autor Tema: Recibir trama de bytes por RS232...  (Leído 4205 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado I3iT

  • PIC12
  • **
  • Mensajes: 50
Recibir trama de bytes por RS232...
« en: 10 de Mayo de 2005, 15:46:00 »
Wenas a to2.

Os comento un problema que me ha surgido en una aplicacion que estoy desarrollando, 16F876A.

El PIC manda unos datos al PC para graficarlos -> Funciona (aplicacion en Visual Basic)

El PC manda codigos al PIC para configurarlo, le mando:
       byte1 -> Cabecera que indica si es un check de conexion o cambio de modo, los cuales tengo programado PWM+ o PWM-
      byte2 -> PWM_pos o PWM_neg
      byte3 y byte4 -> Valor a cargar en el PWM:
                                 duty_PWM2=make16(byte4,byte3);

El timer1 me indica el periodo de muestreo, para recojer los datos (encoder).
Tanto el timer como el PWM2 funcionan, estan bien configurados.

El problema es al recibir datos por USART, el PIC se me resetea de forma aleatoria. Quiero decir que esta recibiendo cambios de velocidad bien (mientras grafica) y de repente al recibir otro cambio de velocidad por USART se resetea (WDT activo).

He probado a recibir por interrupcion los 4 bytes seguidos, de 1 byte cada vez (codigo parecido al que tiene PACA en su web, gracias por compartirlo) o a recibir muestreando.

Incluso muestreando recibir 2 bytes, responder al PC y quedar a la espera de los otros 2 bytes.

 
Codigo:

#include <16F876A.h>
#fuses XT,WDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,BITS=8)

// Cabeceras que pueden llegar desde el HOST:
#define      CHEQUEO      0xF0         // Chequeo de conexion, PIC responde ACK.
#define      MODO_REF   0xF1         // Modo de control; velocidad, posicion, PWM




// En el main:

if(bit_test(PIR1,5)){   
  disable_interrupts(INT_TIMER1);

  cabecera=getc();
  restart_wdt();
  switch(cabecera){
    case CHEQUEO:
    putc(0xFA);         // Respondemos: "acknowledge" (FA)
    break;

   case MODO_REF:    // Recibe modo + Referencias
    modo=getc();
    switch(modo){
        case(PWM_pos):
        case(PWM_neg):
          putc(0xFA);                   // Respondemos: "acknowledge" (FA)
          refer_h=getc();   // Recibimos parte alta y baja para referencia.
          refer_l=getc();
          duty_PWM2=make16(refer_h,refer_l);
          break;
    break;
  }

  enable_interrupts(INT_TIMER1);
}





Solicito de vuestra ayuda, no me quedan ideas y me niego a creer que no pueda recibir una trama de 4 bytes consecutivos.


En el caso de recepcion por interrupcion, algo de lo que he intentado es esto:
Codigo:

// --------------------------------------------------------------------------------------------------
// Rutina de atencion a la interrupcion por recepcion USART.
// Se recibe una trama de 4 bytes, el primero es la cabecera e indica que datos siguen.
// cabecera:   CHEQUEO      0xF0
//            MODO_REF   0xF1  +  MODO  +  2bytes(valor)
//            PARAMETROS   0xF2  +  Kn    +  2bytes(valor)
//            CONFIG_ROM   0xF3  +  Kn    +  2bytes(valor)
// --------------------------------------------------------------------------------------------------
#int_RDA
void serial_isr(){
  disable_interrupts(INT_TIMER1);
  // Si hay una trama pendiente de analizar se ignora lo recibido.
  if (comm_ocupado==0){
    comm_trama[0]=getc();
    comm_trama[1]=getc();
    comm_trama[2]=getc();
    comm_trama[3]=getc();

    // Indicamos que hay nuevos datos a tratar:
    comm_ocupado=1;

  }
  enable_interrupts(INT_TIMER1);
}


Con el correspondiente enable_interrupts(int_rda);

No os aburro mas, que estoy muy quemao con la puta USART....

>Salu2<

Desconectado wqtrp

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 170
RE: Recibir trama de bytes por RS232...
« Respuesta #1 en: 14 de Mayo de 2005, 15:52:00 »
hola, mire un poco el codigo, y al menos en la parte q recibe por interrupcion pareciera q asumes q te llegan 4 bytes juntos y esto no siempre es asi, no con los tiempos de el micro, con lo cual lo normal seria q tengras una int y recibas un byte y luego sigas con tu prog. hasta q llegue el 2do y 3ro y cuarto y recien ahi habilitar la recepcion de la trama completa.

Desconectado adrian2a1

  • Colaborador
  • PIC12
  • *****
  • Mensajes: 75
RE: Recibir trama de bytes por RS232...
« Respuesta #2 en: 15 de Mayo de 2005, 03:31:00 »
¿Por qué no deshabilitas el Watchdog?. A primera vista el Watchdog en tu programa no tiene utilidad alguna, y te recuerdo que resetea el sistema si no se actualiza antes de tiempo (entre 18 ms y 2.3 segundo según lo tengas configurado).


Desconectado I3iT

  • PIC12
  • **
  • Mensajes: 50
RE: Recibir trama de bytes por RS232...
« Respuesta #3 en: 15 de Mayo de 2005, 11:42:00 »
adrian: El watchdog lo tengo por si se produce algun error en la comunicacion el pic se reinicie y tenerlo en un estado conocido. Es como seguridad ante fallos en la comunicacion.
Lo reseteo en el programa principal, eso funciona perfectamente pues solo se me reinicia el pic cuando se queda a la espera en un getc() y no regresa de la funcion de recepcion al main, que es donde reseteo el watchdog.


wqrtp: Espero recibir 4 bytes pues se los mando seguidos desde el PC y pensaba que el PIC los recibiria bien asi, pero no le gustaba...
Tambien probe recibir byte a byte, y al tener 4 activar un flag para tratar la trama, basado en el ejemplo que tenia pacalaconcurso en su web.


Codigo:
// --------------------------------------------------------------------------------------------------
// Rutina de atencion a la interrupcion por recepcion USART.
// Se recibe una trama de 4 bytes, el primero es la cabecera e indica que datos siguen.
// cabecera:   CHEQUEO      0xF0
//            MODO_REF   0xF1  +  MODO  +  2bytes(valor)
//            PARAMETROS   0xF2  +  Kn    +  2bytes(valor)
//            CONFIG_ROM   0xF3  +  Kn    +  2bytes(valor)
// --------------------------------------------------------------------------------------------------
#int_RDA
void serial_isr(){

   if(comm_cuenta<4){

       comm_trama[comm_cuenta]=getc();

      // Cuando comm_cuenta==4, tendremos la trama completa lista para procesar.
      comm_cuenta++;
   }
}


Ahora mismo funciona bien haciendolo por muestreo, if(bit_test(PIR1,5)), he tenido que retocar un poco el programa del PC pero creo que ya recibe sin problemas cada dos por tres.

Leyendo otros post, vi este: http://miarroba.com/foros/ver.php?foroid=15353&temaid=1777135
Aqui dogflu66 comenta:
"para trabajar la usart + interrupciones yo no utilizo menos de 20Mhz, de esta forma me evito que se bloquee, ya que si no extraes los datos suficiente mente rápido se bloquea em Rx y entonces tienes que llevar el control de errores de la usart para detectar este fallo y obrar en consecuencia..."

Entonces ¿podria ser que al trabajar con un reloj a 4 Mhz no le de tiempo al PIC a recojer los bytes antes de que llegen mas, lo que produce un bloqueo del mismo?

Desconectado wqtrp

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 170
RE: Recibir trama de bytes por RS232...
« Respuesta #4 en: 15 de Mayo de 2005, 11:52:00 »
no, no puede ser, con 4Mhz tiene una instrucion cada microseg. con lo cual a menos q la interuupcion sea un programa enormew, eso no puede pasarte, para transferir un byte a 9600 son casi un miliseg.

Desconectado adrian2a1

  • Colaborador
  • PIC12
  • *****
  • Mensajes: 75
RE: Recibir trama de bytes por RS232...
« Respuesta #5 en: 15 de Mayo de 2005, 16:25:00 »
Sigo sin ver claro la utilidad del Watchdog en tu programa, ahí está la causa de tu problema. De todas formas si insistes en mantenerlo no puedes utilizar la instrucción getc() tal como lo haces, porque siempre el sistema será reseteado por el Watchdog. Prueba con la sigueinte estructura, utilizando la función kbhit() y restart_wdt() en la rutina de atención a la interrupción y similar en el programa principal:

Codigo:
#int_RDA
void serial_isr()
{
     if(comm_cuenta<4)
     {
          if (kbhit())
          {
        comm_trama[comm_cuenta]=getc();
        comm_cuenta++;
          }
          else
        restart_wdt();
     }
}


Aunque, te insisto que yo deshabilitaría el Watchdog. Podiamos entrar en una discusión en la utilidad del mismo, pero yo lo tengo muy claro: para programas sencillos lo único que hace el Watchdog es complicar la vida al personal, te lo cuento por experiencia.

Salu2.

Adrian.

Desconectado I3iT

  • PIC12
  • **
  • Mensajes: 50
RE: Recibir trama de bytes por RS232...
« Respuesta #6 en: 18 de Mayo de 2005, 15:06:00 »
Gracias a ambos por la ayuda.

Comentaros que ya continuare con la comunicacion USART por interrupcion, probare con kbhit(). Por ahora lo dejo por muestreo, ya que asi parece que no da errores (por fin) y continuo con la aplicacion que me corre mas prisa tenerlo funcionando. Cuando este terminado retomaré esta parte.

Gracias de nuevo y salu2.