TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: Nocturno en 20 de Septiembre de 2009, 09:05:23

Título: Detectar fin de transmisión
Publicado por: Nocturno en 20 de Septiembre de 2009, 09:05:23
Hoy he estado peleando con una comunicación RS485 y he tenido que utilizar un recurso que jamás había usado y me ha venido como anillo al dedo.
Supongo que muchos de vosotros ya lo conoceréis, pero lo voy a escribir por si es de utilidad a alguien que tenga el mismo problema que yo.

El RS485, además de las señales TX y RX, requiere de una señal más que indica en cada momento si estamos transmitiendo o recibiendo, para lo que se utiliza un pin adicional del PIC. En mi caso este pin va conectado a dos pines del MAX485 indicando con un 1 que estamos transmitiendo y con un 0 que estamos recibiendo.

El estado habitual de mi circuito es "escuchando", y sólo se pone esa señal a 1 cuando trasmite, volviendo a 0 una vez finalizada la comunicación.
Y aquí aparece el problema. Tras un printf en CCS, el programa descarga sobre la USART la labor de envío de los bytes, y continúa su ejecución, por lo que si bajamos la señal a 0 justo detrás del printf lo normal es que cortemos la transmisión antes de que haya terminado.

Pues bien, para esperar a que la transmisión termine he utilizado un bit de la USART llamado TRMT, en el registro TXSTA (estoy trabajando con un 18F). Este bit permanece a 0 mientras haya una transmisión pendiente.

Mi código por tanto tiene estas definiciones al principio:
#define TXSTA  0xFAC
#bit TRMT =  TXSTA.1

Y luego, cuando transmito me limito a lo siguiente:
      RS485_emite();
      printf ("Hola mundo");
      while (!TRMT);
      RS485_recibe();

Bueno, pues como veis es una chorradita, pero me ha hecho perder toda la mañana, así que se ha merecido al menos este post.

(*) Las funciones RS485_emite y RS485_recibe se limitan a poner a 1 y a 0 el pin que antes describí.
Título: Re: Detectar fin de transmisión
Publicado por: MLO__ en 20 de Septiembre de 2009, 11:27:59
Hola.

Cuando trabaje con el RS485 tuve problemas algo similares, los cuales se solucionaron dejando un delay_ms(2) luego del final de la transmisión. Muy elegante solución maestro.

Saludos
Título: Re: Detectar fin de transmisión
Publicado por: migsantiago en 20 de Septiembre de 2009, 14:11:31
Lo mismo nos pasó a Akenafab y a mi con los sn75176b.

La solución fue similar a la que comenta MLO, colocar un delay, pero nosotros calculamos el tiempo que tarda un byte en enviarse por rs232...

Velocidad 9600bps = 960B/s

Dividido en 10 por el bit start, 8 bits de datos y bit stop. La velocidad por un byte es entonces la inversa: 1.0416us/B.

El código nos quedó así:

Código: [Seleccionar]
output_high(TX_ENABLE); //Habilita terminal TX para envío
//Envía el paquete 3 veces para redundancia
for(j=0; j<3; ++j)
   {
   for(i=0; i<8; ++i)
      {
      putc(com_tx[i]);
      delay_us(1042); //En lo que se envía el byte por serial
      }
   }
output_low(TX_ENABLE);  //Deshabilita para recibir

Cabe señalar que putc nunca envía un byte si no se ha terminado de enviar el anterior, pero al enviar un último byte sí es necesario agregar el delay antes de desactivar TX en el módulo rs485.
Título: Re: Detectar fin de transmisión
Publicado por: RedPic en 20 de Septiembre de 2009, 14:15:13
Código: CSS
  1. /** \brief Envía un mensaje por el Canal RS485 (vía Canal Serie USART)
  2.   *
  3.   * Envia un mensaje conmutando el Canal serie hacia el Canal RS485. Restaura las comunicaciones estandar tras enviar el mensaje.
  4.   *
  5.   * \param psMessage Puntero a un string con el comando a enviar.
  6.   *
  7.   * \return void
  8.   *
  9.   */
  10. void USART_send_message_485(char* psMessage){
  11.  
  12.    open_485_for_transmit();
  13.    delay_25();
  14.    printf("%s\r\n",psMessage);
  15.    delay_25();
  16.    close_485_after_process();
  17. }
Título: Re: Detectar fin de transmisión
Publicado por: Nocturno en 20 de Septiembre de 2009, 14:15:56
Santiago, en tu caso podrías poner el delay fuera del bucle, para sólo esperar cuando se transmita el último byte, puesto que los anteriores ya van siguiendo su ritmo a medida que la usart se va quedando libre.
Título: Re: Detectar fin de transmisión
Publicado por: migsantiago en 20 de Septiembre de 2009, 14:27:05
Sip. Aunque a final de cuentas es igual creo yo... un ejemplo de envío de 2 bytes...

- Poniendo el delay_us después de cada putc
  + Putc pone el 1er byte en TXREG
  + Pasa el delay y TXREG ya estará vacío
  + Putc pone el 2do byte en TXREG
  + Pasa el delay y TXREG ya estará vacío
  Tiempo total: 2 delays_us (justamente equivalentes a envío de 2 bytes)

- Poniendo el delay_us después de que los dos bytes se han enviado
  + Putc pone el 1er byte en TXREG
  + Putc espera a que se vacíe TXREG (el 1er byte todavía se está enviando)
  + Putc pone el 2do byte en TXREG
  + Pasa el delay_us del final (tarda un tiempo equivalente a 1 byte)
  Tiempo total: 1 periodo de envío de 1 byte más un delay_us

Ambas tardan casi lo mismo... aunque poniendo el delay_us al terminar el envío de todo byte nos ahorra unos cuantos nanosegundos por la precisión de los delays internos del primer método ;-)
Título: Re: Detectar fin de transmisión
Publicado por: RedPic en 20 de Septiembre de 2009, 14:35:21
Otra posible solución es utilizar la #INT_TBE que nos salta cuando el buffer de transmisión de la USART se queda vacío.

Yo nunca la he utilizado pero sería similar a la #INT_EEPROM que si uso para saber cuando ha terminado de escribir la EEPROM y así no uso delay aproximado sino que se cuando puedo continuar.

Edito: Esto es algo similar a lo que haces, Manolo, con el bit TRMT

Título: Re: Detectar fin de transmisión
Publicado por: Nocturno en 20 de Septiembre de 2009, 15:07:14
Antes de probar con el método del bit, he estado peleando con esa interrupción, la #INT_TBE. Seguro que lo he hecho mal porque no lo he conseguido.
Título: Re: Detectar fin de transmisión
Publicado por: MLO__ en 20 de Septiembre de 2009, 21:17:57
Creo yo que la mejor alternativa si es checar el estado del registro, aunque, cuando las lineas de transmisión son muy largas, puede haber cierto "retraso" en relación  al dato recibido, por lo que habría que verificarlo experimentalmente.

Saludos
Título: Re: Detectar fin de transmisión
Publicado por: AKENAFAB en 20 de Septiembre de 2009, 21:36:20
Paso lo que comenta Santiago

Y le mandaba muchos mensajes xD porque a usar putc este espera a que termine la transmision , sin embargo , se perdía un byte .Recuerdo hasta enviarle varias imagenes con los tiempos de transmision y se apreciaba el byte perdido , en si el tiempo de este cuando poniamoso en low la habilitacion de transmision.

Con el retardo fuera del ciclo no funcionaba correctamente.

Yo le insistia en que habia un bit xD porque lo usaba en asm ,luego me confundi mucho xD y lo dejamos con el retardo.
Por las prisas y demas problemas que daba con el compilador ya no probe bien el bit,me confundo con el TSR.

Con el retardo quedo solucionado.

Probare nuevamente con el bit y les cuento lo que ocurre.
Título: Re: Detectar fin de transmisión
Publicado por: migsantiago en 20 de Septiembre de 2009, 21:40:46
Checa con el bit TXIF de la interrupción, yo lo busqué hace rato pero no lo encontré.
Título: Re: Detectar fin de transmisión
Publicado por: AKENAFAB en 20 de Septiembre de 2009, 21:54:37
Lo acabo de revisar y ya se donde esta la confusion xD

Con TXIF y TRMT .

Primero se carga el TXREG y de ahi lo `pasa al TSR .

putc revisa el TXIF

Cuando termina de enviar el ultimo bit por el TSR se pone a 0 y el byte ya ha salido del micro.

Saludos!
Título: Re: Detectar fin de transmisión
Publicado por: BrunoF en 21 de Septiembre de 2009, 00:07:33
Muchachos por ahi estoy equivocandome, o no estaban al tanto pero exìste en el CCS un modificador del RS-232 llamado ENABLE que permite configurar el pin que se utiliza en los IC's que lo requieren(gralmente para RS485).

Este comando(ENABLE) permite seleccionar el bit del uC al cual conectamos nuestro integrado(en mi caso sn75176) y asi utomaticamente el CCS lo configure antes de enviar una trama y luego de terminado su envio...

Código: [Seleccionar]
ENABLE=pin
 The specified pin will be high during transmit.  This may be used to enable 485 transmit.

 
Título: Re: Detectar fin de transmisión
Publicado por: BrunoF en 21 de Septiembre de 2009, 00:12:27
Otro problema que tuve usando el SN75176 fue que si conectaba el pin del uC a ambos pines, !RE y DE, tenia problemas para recibir la trama.

Revisando a fondo el datasheet del SN75176 descubrì que lo correcto es conectar permanentemente !RE a GND y controlar sòlo el pin DE desde el uC.

Saludos.
Título: Re: Detectar fin de transmisión
Publicado por: Nocturno en 21 de Septiembre de 2009, 02:54:49
San Bruno, ¿porqué no lo dijiste antes?  :D

Eres grande, tengo que probar eso.
Título: Re: Detectar fin de transmisión
Publicado por: BrunoF en 21 de Septiembre de 2009, 03:20:31
Ea! Que sólo he llegado con un día de retraso.Ya lo sé: una eternidad cuando uno está atascado y no sabe ya que mas probar. :D
Título: Re: Detectar fin de transmisión
Publicado por: RedPic en 21 de Septiembre de 2009, 04:16:45

Revisando a fondo el datasheet del SN75176 descubrì que lo correcto es conectar permanentemente !RE a GND y controlar sòlo el pin DE desde el uC.


 :shock: :shock: :shock: A que he estado haciendo el tonto durante dos años (con problemas de recepción)  :D :D :D
Título: Re: Detectar fin de transmisión
Publicado por: BrunoF en 21 de Septiembre de 2009, 04:23:44
Ufff no me digas!

Espero que sea por eso...yo he tenido graves problemas de recepción compartiendo el pin que comanda a ese integrado.

P.D. Mis acentos van para cualquier lado, mi teclado ha cobrado vida y se configura como le apetece, o bien hay fuertes vientos azotando mis palabras... :mrgreen: :mrgreen:
Título: Re: Detectar fin de transmisión
Publicado por: stk500 en 21 de Septiembre de 2009, 05:02:22
Quizas tambien os interese esta informacion ya que aqui no va ningun pin va a GND , se controla por Software, abajo vera el codigo hecho en C.
http://next.nxp.com/acrobat/applicationnotes/AN10717_1.pdf
Título: Re: Detectar fin de transmisión
Publicado por: AKENAFAB en 21 de Septiembre de 2009, 08:39:14
Otro problema que tuve usando el SN75176 fue que si conectaba el pin del uC a ambos pines, !RE y DE, tenia problemas para recibir la trama.

Revisando a fondo el datasheet del SN75176 descubrì que lo correcto es conectar permanentemente !RE a GND y controlar sòlo el pin DE desde el uC.

Saludos.

Siempre los conecte juntitos , pero tenia problemas de recepción , siempr ehe visto que los conectan juntos , pero probaré lo que propones.

Ahora usamos rs-422
Título: Re: Detectar fin de transmisión
Publicado por: MLO__ en 21 de Septiembre de 2009, 11:52:56
Hola.

Pues yo los conectaba juntos por miedo a que haya conflictos por tener los dos el mismo estado. Pero revisando el datasheet:
(http://img38.imageshack.us/img38/6554/driverf.png)

Esta muy claro que no depende para nada del pin ~RE ... y la verdad, ni tan a fondo hay que revisarlo  :D ....... ahí esta, claro como siempre .. un punto mas para el datasheet y uno menos para mi por pasar las hojas de éste muy rapido.

Saludos
Título: Re: Detectar fin de transmisión
Publicado por: ALE1973 en 21 de Septiembre de 2009, 22:41:21
Hola, use en varios proyectos el 75176b, siempre e unido los pines DE y RE, nunca tuve problemas, en CCS, me gusta usar la interrupcion por TBE, ya que asi evito que el micro quede en un bucle hasta que se libera el registro de la USART, lo que hago es llenar un array y luego desde la rutina de interrupcion incremento el puntero del array para ir enviando byte a byte, cuando envio el ultimo, bajo el pin de habilitacion de 75175b, el cual habilite antes de habilitar la transmision.

1.- Lleno array de transmision
2.- Habilito 75176b
3.- Habilito interrupcion por TBE
4.- Despues de enviar el ultimo byte, deshabilito 7176b

Código: CSS
  1. #INT_TBE
  2. void serial_tx(){
  3.    if(txlen!=0){
  4.       putc(txbuff[txpoint]);
  5.       txpoint++;
  6.       txlen--;
  7.    }
  8.    else{
  9.    disable_interrupts(int_tbe);
  10.    inicbuffTX();
  11.    txpoint=0;
  12.    oUtput_low(PIN_C0);
  13.    }
  14. }

Ese codigo es el que uso para la transmitir un buffer.
Espero les sea de  utilidad..

Saludos.
Alejandro

Edito, probe a user el modificador ENABLE en users232, pero en algunas ocaciones supe tener fallas.
Título: Re: Detectar fin de transmisión
Publicado por: migsantiago en 21 de Septiembre de 2009, 22:48:22
Vaya... un problema que a todos nos ha pasado pero que todos teníamos bien calladito  :D

Ahora hay más de una solución al respecto.  :mrgreen:
Título: Re: Detectar fin de transmisión
Publicado por: AKENAFAB en 21 de Septiembre de 2009, 23:59:48
Vaya... un problema que a todos nos ha pasado pero que todos teníamos bien calladito  :D

Ahora hay más de una solución al respecto.  :mrgreen:

Si que si!
Título: Re: Detectar fin de transmisión
Publicado por: Nocturno en 22 de Septiembre de 2009, 02:07:08
Y yo que pensé en ni siquiera abrir el hilo porque me parecía una chorrada; ahora me alegro de haberlo hecho porque estoy aprendiendo un huevo.