PIC24FJ64GB002 UART Bridge

2

Trabajo en un proyecto pero tengo un problema.

Quiero hacer un programa que conduzca los dos UART en un PIC, cada UART a una velocidad de transmisión diferente. La idea es tomar una señal para UART1 (9600 baudios) y enviarla a la salida UART 2 (1200 baudios). En el momento en que hago un código para conducir los dos UART.

Adjunto el código, y esto tiene comentarios en la prueba de eco, y los uart se ejecutan bien, cuando pongo los datos en uart 2, estos datos están bien en la salida a UART 1, pero, cuando quiero ingresar datos UART 1, para ver estos datos en la salida de uart 2, perdí muchos datos por diferentes velocidades de transmisión. Espero hacerme entender, mi problema es la pérdida de datos desde una velocidad de transmisión alta a una velocidad de transmisión baja, espero su opinión sobre cómo resolver esto.

#if defined (__PIC24F__)
#include <p24FJ64GB002.h>
#endif
#include "xc.h"

_CONFIG4(DSBOREN_OFF & DSWDTEN_OFF)
_CONFIG3(WPDIS_WPDIS)
_CONFIG2(POSCMOD_NONE & OSCIOFNC_OFF & FNOSC_FRC & PLL96MHZ_OFF )
_CONFIG1(FWDTEN_OFF & JTAGEN_OFF)

 int c,D;


int main(void){


    //OSCILLATOR CONFIG
    OSCCON=0X0000;          //
    CLKDIVbits.RCDIV0=0; //clock divider to 0

    //PIN CONFIG

    AD1PCFGL=0XFFFF;            //ALL PINS DIGITAL
    TRISA = 0X0000;                  //PORT A OUTPUT
    TRISB = 0XFFFF;                  //PORT B INPUT

    RPOR2bits.RP5R=3;           // RP5  TX UART1
    RPOR3bits.RP6R=5;           // RP6  TX UART2

    RPINR18bits.U1RXR=0;        //RP0  RX UART1
    RPINR19bits.U2RXR=2;        //RP1  RX UART2

    //----------------------------------------------------------------------------

    //UART CONFIG

    U1BRG=103;
    U2BRG=832;

    U1MODEbits.UARTEN = 1; // UART Enable
    U1MODEbits.USIDL = 1;// Stop in Idle Mode Bit
    U1MODEbits.IREN = 0; // IrDA Encoder and Decoder Disabled
    U1MODEbits.RTSMD = 1; // UxRTS in SIMPLEX mode
    U1MODEbits.UEN = 00; // Tx and Rx pins are used,UxCTS,UxRTS, BCLK are controlled by port latch
    U1MODEbits.WAKE = 0; // Wake up disabled on sleep mode
    U1MODEbits.LPBACK = 0; // Loopback is disabled
    U1MODEbits.ABAUD = 0; // Baud rate measurement is disabled
    U1MODEbits.RXINV = 0; // Idle state is '1'
    U1MODEbits.BRGH =1; // High baurdate selected
    U1MODEbits.PDSEL = 00 ; // No parity, 8bits
    U1MODEbits.STSEL = 0; // 1 Stop bit

    U2MODEbits.UARTEN = 1; // UART Enable
    U2MODEbits.USIDL = 1;// Stop in Idle Mode Bit
    U2MODEbits.IREN = 0; // IrDA Encoder and Decoder Disabled
    U2MODEbits.RTSMD = 1; // UxRTS in SIMPLEX mode
    U2MODEbits.UEN = 00; // Tx and Rx pins are used,UxCTS,UxRTS, BCLK are controlled by port latch
    U2MODEbits.WAKE = 0; // Wake up disabled on sleep mode
    U2MODEbits.LPBACK = 0; // Loopback is disabled
    U2MODEbits.ABAUD = 0; // Baud rate measurement is disabled
    U2MODEbits.RXINV = 0; // Idle state is '1'
    U2MODEbits.BRGH =1; // High baurdate selected
    U2MODEbits.PDSEL = 00; // No parity, 8bits
    U2MODEbits.STSEL = 0; // 1 Stop bit

 //------------------------------------------------------------------

    //CONFIGURACION DE TRANSMISION, RECEPCION E INTERRUPCIONES DE LAS UART

    U1STAbits.UTXINV = 0; // UxTX idle state is '0'
    U1STAbits.UTXBRK = 0; // Sync Break Disabled
    U1STAbits.UTXEN = 1; // UART1 Transmitter  is enabled
    U1STAbits.URXISEL = 00; // Interrupt flag bit is set when a charater is received
    IEC0bits.U1TXIE = 0; // Disable UART1 Tx interrupt

    U2STAbits.UTXINV = 0; // UxTX idle state is '0'
    U2STAbits.UTXBRK = 0; // Sync Break Disabled
    U2STAbits.UTXEN = 1; // UART2 Transmitter  is enabled
    U2STAbits.URXISEL = 00; // Interrupt flag bit is set when a charater is received
    IEC1bits.U2TXIE=0;      // Disable UART2 Tx interrupt

         while(1){
//         //ECHO TEST UART 2 1200 BAUDS
//         //wait for byte
//         while(!U2STAbits.URXDA);
//         c=U2RXREG;//get byte
//         //wait for empty spot in transmit buffer
//         while(U2STAbits.UTXBF == 1);
//         //echo received character back
//         U2TXREG = c;


////         //ECHO TEST UART 1 9600 BAUDS
//         //wait for byte
//         while(!U1STAbits.URXDA);
//         D=U1RXREG;//get byte
//         //wait for empty spot in transmit buffer
//         while(U1STAbits.UTXBF == 1);
//         //echo received character back
//         U1TXREG = D;

//TEST TO PUT UT DATA FROM UART 2 1200 IN OUTPUT UART1 9600, ITS PART IS OK

         while(!U2STAbits.URXDA);
         D=U2RXREG;//get byte
         //wait for empty spot in transmit buffer
         while(U2STAbits.UTXBF == 1);
         //echo received character back
         U1TXREG = D;

         }

    return 0;
}
    
pregunta Gabeto

2 respuestas

4

Por lo que entiendo, estás preguntando: tienes 2 UART a diferentes velocidades. Envía datos a la UART rápida, y la envía a través de la UART lenta para usted, y el problema que tiene es que pierde datos porque no se envían lo suficientemente rápido.

Ok. La respuesta es usar un sistema llamado "Almacenar y reenviar". Esto se ha utilizado durante muchos años en concentradores Ethernet 10/100, donde los datos que ingresan pueden ser 10 veces más rápidos que los datos que salen.

Básicamente, implica que tienes un búfer grande (generalmente circular) que se llena con el UART rápido, y se escurre fuera del UART lento.

Solo funciona realmente si tiene una forma de datos de "ráfaga", es decir, no está enviando datos todo el tiempo, sino enviando paquetes de fragmentos con retrasos intermedios. Esto permite que el lento UART alcance y haga espacio en el búfer circular para obtener más datos.

En un sistema perfecto, usarías un apretón de manos para decirle al remitente rápido que deje de enviar por un tiempo. Lo mejor es el handshaking de hardware, donde se usa una línea de IO para indicar al remitente que se trata de datos "Clear To Send" (CTS). Algunos chips (PIC32) tienen esta funcionalidad incorporada con pines CTS / RTS dedicados, pero es lo suficientemente simple como para emularlo en aquellos que no lo tienen.

Otra alternativa es usar el software handshaking, también conocido como XON / XOFF, donde el PIC24 enviaría un carácter XOFF cuando su buffer esté casi lleno, y un carácter XON cuando se vuelva a vaciar. Estos niveles se conocen como "marca de agua alta" y "marca de agua baja" respectivamente, ya que todo el sistema se puede considerar como un tanque lleno por un tubo de gran diámetro y un pequeño orificio en el fondo que gotea agua. Una válvula cerraría el agua en la "marca de agua alta" y permitiría que fluya nuevamente en la "marca de agua baja".

Tenga en cuenta que la marca de límite superior no es lo mismo que el búfer que está lleno, solo que está "casi" lleno, ya que el software no es perfecto, y algunos datos aún pueden aparecer después de enviar XOF debido a cualquier búfer entre los El software del remitente y el hardware del receptor.

    
respondido por el Majenko
2

Mientras espera un lugar vacío en el búfer de tx para el UART lento, es probable que deje que el búfer de rx de la UART más rápida se supere al no procesar esos bytes lo suficientemente rápido. Una forma típica basada en software para hacer esto es crear su propio búfer en su software y leerlo / escribirlo sin bloquear la espera de la disponibilidad de rx / tx (otras soluciones son el protocolo de enlace como se describe en La respuesta de Majenko ).

Un buffer de anillo es generalmente una solución fácil de implementar. Algo así como, pseudo-código:

unsigned char buffer[128];
int rxposition = 0, txposition = 0;

while (1) {

    /* If RX data, read it into our buffer. Otherwise do not wait. */
    if (U2STAbits.URXDA) {
        buffer[rxposition++] = U2RXREG;
        rxposition &= 127; /* Optimization of: rxposition %= sizeof(buffer); for size 128 */
    }

    /* If TX available and we have data to write, write it. Otherwise do not wait. */
    if (!U2STAbits.UTXBF && rxposition != txposition) {
        U1TXREG = buffer[txposition++];
        txposition &= 127; /* Optimization of: txposition %= sizeof(buffer); for size 128 */
    }

}

El fragmento de código anterior no contiene protección contra el desbordamiento del búfer de entrada, y es con fines ilustrativos (sin duda, usted rebasará el búfer de entrada si transmite datos continuamente a la UART rápida; su tasa de datos promedio a la UART rápida aún debe ser & lt ; = la velocidad en baudios lenta para hacer que su tarea sea posible) - aunque vale la pena señalar que es posible que no necesite ningún tipo de protección adicional si la eliminación de bloques de bytes arbitrarios ~ sizeof(buffer) en una saturación es un comportamiento aceptable. Se eligió una potencia de 2 tamaños de búfer solo para optimizar la operación de módulo, pero todo funcionará siempre que su búfer sea lo suficientemente grande como para manejar su situación.

    
respondido por el Jason C

Lea otras preguntas en las etiquetas