Autor Tema: Recepción serie por soft usando el Timer  (Leído 5732 veces)

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

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Recepción serie por soft usando el Timer
« en: 16 de Noviembre de 2009, 15:12:32 »
A veces tenemos que utilizar más de una USART y nuestro micro no tiene más que una.
La emulación software de una USART que trae CCS nos ha sacado a todos de más de un apuro pero tiene un inconveniente importante: mientras envías o recibes un byte pierdes el control del micro, y tu programa se queda esperando a que la rutina de envío o recepción finalice.

En mi caso estoy trabajando con un 18F a 12MIPS y he necesitado implementar una recepción serie por software a 1200 baudios. Esto quiere decir que mientras mi micro recibe un byte, tiene que esperar:
1200 baudios -> cada bit dura 833us -> cada byte tiene 1 bit start + 8 bits datos + 1 bit stop = 10 bits -> total espera 8330 us = 8.3ms

En ese tiempo el micro a 12MIPS habría podido ejecutar 100.000 instrucciones, y en según que aplicaciones no te puedes permitir ese derroche de recursos.

Para no tener esa pérdida de tiempo, y puesto que tenía un Timer libre, he escrito esta pequeña rutina que recibe un byte usando cualquier pin. Lógicamente se podría modificar para que la recepción la hiciera sobre un buffer y para distintas velocidades de transmisión pero no era mi propósito hacer una rutina tan compleja:

Código: C
  1. #int_timer1
  2. void RecibeByte() {
  3.    static int8 Capturando,Dato,BitsLeidos;
  4.  
  5.    set_timer1(55535);           // Esta precarga está calculada para 1200 baudios = 833us
  6.  
  7.    if (Capturando) {            // Ya estábamos capturando el byte
  8.       if (++BitsLeidos==9) {    // Si hemos capturado el último bit
  9.          Capturando=0;          // ya no capturamos más
  10.          ByteRecibido=Dato;     // Cargamos el dato sobre una variable global. Aquí se podría almacenar sobre buffer
  11.       } else {
  12.          Dato=Dato*2+input(PIN_D3);     // acumulamos el bit recibido en el pin D3  
  13.         }
  14.    } else {
  15.       if (!input(PIN_D3)) {     // He leído un cero, que es el bit de Start
  16.          BitsLeidos=0;          // Inicializamos las variables
  17.          Dato=0;
  18.          Capturando=1;
  19.       }
  20.    }
  21. }

Como he dicho antes, la rutina se puede mejorar para hacerla más flexible a otras circunstancias, y también se puede escribir una análoga para hacer la transmisión con el Timer, pero esa tarea la dejaré para quien esté interesado en hacerla.

Espero que sirva de ayuda

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: Recepción serie por soft usando el Timer
« Respuesta #1 en: 19 de Noviembre de 2009, 08:21:53 »
Que tal manolo!
Estaba revizando tu rutina porque me parecio interesante tu propuesta de la rutina serie por software  :mrgreen: , pero a medida que la veia me comensaron a surgir varias dudas  :shock:

Tu empleas la interrupcion por el timer1 en tu ejemplo y segun dices esta rutina permite capturar un byte recibido serialmente, pero no logro entender como sincronizas el byte a recibir con la rutina  :(

En otras palabras como configuras la rutina desde el main para poderla emplear?
Podrias colocar un ejemplito por ejemplo donde este suponte parpadeando un led y cuando se envie un dato serial este lo lea para poder asi ver, como sincronizas el byte que llega con la rutina que colocastes?

De antemano gracias!  :mrgreen:

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: Recepción serie por soft usando el Timer
« Respuesta #2 en: 19 de Noviembre de 2009, 08:33:58 »
Que tal manolo!
Otra vez yo   :D
Creo que la respuesta a mi pregunta esta en este pequeño fragmento  :shock:
Citar
#
if (!input(PIN_D3)) {   // He leído un cero, que es el bit de Start
#
        BitsLeidos=0; // Inicializamos las variables
#
        Dato=0;
#
        Capturando=1;
Alli es donde capturas el bit de start y de esa manera sincronizas los bits que van llegando, estare en lo correcto?  :mrgreen:

Saludos

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #3 en: 19 de Noviembre de 2009, 08:41:28 »
La sincronización se basa en que el periodo de la interrupción del timer sea el mismo que el de cada bit de la comunicación serie.
De esta manera, cuando tú inicializas el PIC lo único que haces es activar el timer y su interrupción, y desde ese momento cada periodo (833us en mi caso) se asoma a mirar el pin de recepción.

Cuando se lo encuentre a nivel bajo sabrá que ha recibido el bit de start y pone en marcha el mecanismo de captura del byte.

Es así de simple, lo único que te puede aportar mi ejemplo de uso es esto:
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);

P.D.: cuando ya lo tenía escrito veo que lo has averiguado por ti mismo  :D

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: Recepción serie por soft usando el Timer
« Respuesta #4 en: 19 de Noviembre de 2009, 16:24:52 »
 :mrgreen:
Gracias nocturno por la explicacion, probare la rutina!

Saludos

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #5 en: 19 de Noviembre de 2009, 16:39:16 »
Pues ya me contarás luego qué tal te ha ido. Espero que te sirva.

Desconectado fidodido18

  • PIC18
  • ****
  • Mensajes: 312
Re: Recepción serie por soft usando el Timer
« Respuesta #6 en: 20 de Noviembre de 2009, 17:50:54 »
Pues ya me contarás luego qué tal te ha ido. Espero que te sirva.

Oye no se si yo estoy muy lento pero no me doy cuenta en donde estas recibiendo los bit por rs232! en que parte especificamente... y que estas haciendo con el timer?

Lo que medio alcanzo a entender es que el timer vigila un pin cada 833 uS y si llega un dato lo recibe?

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #7 en: 20 de Noviembre de 2009, 18:06:01 »
No es exactamente RS232 porque se supone que ya hemos convertido a niveles TTL, por ejemplo con un MAX232.
El pin por el que lo recibo es el PIN_D3, aunque puedes cambiarlo por el pin que te venga bien.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Recepción serie por soft usando el Timer
« Respuesta #8 en: 20 de Noviembre de 2009, 18:27:44 »
Un detalle que puede resultar interesante para completar este magnifico post del maestro Nocturno.

En mi hilo sobre los Fundamentos de la Transmisión Síncrona os hacía una introducción teórica sobre la Transmisión Asíncrona que es la que utilizamos para transmitir y recibir en RS232 ...

En aquella pequeña introducción definía el etu (elementary time unit) exactamente como el semi-periodo de la frecuencia de transmisión. O sea: el tiempo que dura cada transmisión de un bit.



De hecho el trabajo de don Nocturno lo que hace es implementar dicho etu con el Timer, de forma tal que cada vez que se dispara, o lo que es lo mismo: se consume un etu, se lee un nuevo bit en la linea de recepción.

El detalle al que me refiero es que el primer bit, el Start, es siempre un bit "1", o sea una bajada de la linea, de HIGH a LOW y su posterior subida, de LOW a HIGH, que dura exactamente un etu.

Si la línea de recepción que utilizamos dispone de una Interrupción Externa es fácil implementar un sistema que mida exactamente la duración del etu de ese primer bit de Start. Con esa información es inmediato el poder ajustar el Timer de recepción para que utilice ese etu a partir de la primera lectura.

En otras palabras: Midiendo el ancho de pulso del primer bit de Start podemos tener un ajuste automático de la velocidad de recepción.  :mrgreen:

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #9 en: 20 de Noviembre de 2009, 18:49:57 »
Mmmmm, no lo entiendo, si el primer bit es también a nivel bajo no podrás hacerlo, porque no hay flanco de subida, ¿no?

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Recepción serie por soft usando el Timer
« Respuesta #10 en: 20 de Noviembre de 2009, 18:56:04 »
Estuve buscando, porque crei ver que el CCS tenia la opcion autobaud, pero no lo encuentro... :( :(
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #11 en: 20 de Noviembre de 2009, 19:03:30 »
Sí, lo tiene, querido Marcos, aunque sólo en los micros que dispongan de EUART:

Syntax:
 setup_uart(baud, stream)

setup_uart(baud)

 
 
Parameters:
 baud is a constant representing the number of bits per second. A one or zero may also be passed to control the on/off status.  Stream is an optional stream identifier. 

 

Chips with the advanced UART may also use the following constants: 

UART_ADDRESS UART only accepts data with 9th bit=1

UART_DATA UART accepts all data

 

Chips with the EUART H/W may use the following constants:

UART_AUTODETECT Waits for 0x55 character and sets the UART baud rate to match.

UART_AUTODETECT_NOWAIT Same as above function, except returns before 0x55 is received.  KBHIT() will be true when the match is made.  A call to GETC() will clear the character.

UART_WAKEUP_ON_RDA Wakes PIC up out of sleep when RCV goes from high to low


Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Recepción serie por soft usando el Timer
« Respuesta #12 en: 20 de Noviembre de 2009, 19:05:19 »
No, Manolo, en una transmisión Asíncrona (sin línea de Clock) el bit de Start siempre es un "1", al igual que el de Stop siempre es un "0".

En reposo la linea que recibes siempre está en HIGH.

El primer bit que recibes no es de data sino el de Start que es una transición de HIGH a LOW y de LOW a HIGH que dura exactamente el etu del que hablamos.

A partir de ahí cada periodo etu que transcurra puedes encontrarte la linea en HIGH y entonces leearás un "0" o en LOW y entonces leerás un "1".

Así tantas veces como bits se haya acordado que se van a transmitir.

Al final se reserva un etu a HIGH que se interpreta como un bit de Stop.

Este bit de Stop de un etu de duración se utiliza para separar dos transmisiones consecutivas de dos bytes y que así nos de tiempo, un etu, para procesar el byte recibido.

A partir de ahí volvemos a empezar: Un bit de Start a "1", n bits segun lo acordado y un bit de Stop a "0" para procesarlo.

Mientras que en una transmisión-recepción RS232 todo esto es mas o menos irrelevante, nota que tanto el emisor como el receptor son ajustados en velocidad de forma absolutamente fija y certera, hay transmisiones en las que el etu no está predefinido, se establece por el transmisor justo en el momento de enviar el primer bit, y es obligación del receptor el leer el periodo de dicho etu para poder "entender" lo que se está recibiendo.

El ejemplo mas usual de este tipo de transmisión es el de las Tarjetas chips bancarias. Cuando las energizas tienes que ponerte en recepción y medir la duración del bit start del primer byte que te manda. Esa duración te indica a qué velocidad te va a transmitir el resto de la información.  :mrgreen:


  

Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Recepción serie por soft usando el Timer
« Respuesta #13 en: 20 de Noviembre de 2009, 19:09:02 »
Pues estoy convencido de que tienes razón, pero sigo sin entenderlo.
Llegué a la rutina que he publicado tras hacer pruebas con el osciloscopio y juraría que cuando el primer bit de datos es un nivel bajo de tensión, enlaza el nivel bajo que venía del bit de start prolongándolo por dos etus sin que haya ningún flanco de subida.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Recepción serie por soft usando el Timer
« Respuesta #14 en: 20 de Noviembre de 2009, 19:12:23 »
Sí, lo tiene, querido Marcos, aunque sólo en los micros que dispongan de EUART ...

Esa es otra convención que es muy utilizada. Todo dispositivo que tenga auto-ajuste de la velocidad es "sensible" a la recepción como primer byte del valor 0x55.

Si el primer byte que recibe es 0x55 entonces no lo usa como recibido "normal" sino que lo utiliza para "medirlo" y ajustar la velocidad de transmisión.

Se utiliza precisamente el 0x55 por que es el único byte que tiene todos los bits alternados y empieza por "0".

Así al transmitir el Start + 0x55 + Stop tenemos la secuencia de bits: 1010101010

Curioso y simpático ¿verdad?  :mrgreen:
« Última modificación: 20 de Noviembre de 2009, 19:14:31 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania