Electronic – PIC24FJ64GB002 UART Bridge

bridgepicuart

I work in a project but I have a problem.

I want make a program what drive the two UART in a PIC, each UART at different baud rate. The idea is take a signal for UART1(9600 bauds) and send to UART 2 output (1200 bauds). In the moment i make a code to drive the two UART.

I attach the code, and this have comments in echo test, and the uart´s run ok, when i put data in uart 2, this data is ok in output to UART 1, but, when i want put data in UART 1, to see this data in output of uart 2, i lost many data, by different baud rate. I hope make me understand, my problem is the lost of data from high baud rate to low baud rate, i expect your opinion about how resolve this.

#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;
}

Best Answer

From what I understand you're asking - you have 2 UARTs at different speeds. You send data into the fast UART, and it sends it out through the slow UART for you, and the problem you have is that you lose data as it's not being sent out fast enough?

Ok. The answer is to use a system called "Store and Forward". This has been used for many years in 10/100 ethernet hubs, where data coming in can be 10 times faster than data going out.

Basically it involves you having a large (typically circular) buffer which is filled by the fast UART, and trickles out of the slow UART.

It only really works if you have a "burst" form of data - i.e., you're not sending data all the time, but sending in packets of chunks with delays in between. This allows the slow UART to catch up and make room in the circular buffer for more data.

In a perfect system you would use some handshaking to tell the fast sender to stop sending for a while. The best is hardware handshaking, where an IO line is used to signal to the sender that it's "Clear To Send" data (CTS). Some chips (PIC32) have this functionality built in with dedicated CTS / RTS pins, but it's simple enough to emulate it on those that don't.

Another alternative is to use software handshaking, also known as XON/XOFF where the PIC24 would send an XOFF character when its buffer is nearing full, and an XON character when it's getting empty again. These levels are known as the "High Water Mark" and "Low Water Mark" respectively, as the whole system can be envisaged as a tank being filled by a large bore pipe, and a small hole in the bottom dripping water out. A valve would shut off the water at the "high water mark" and allow it to flow again at the "low water mark".

Note that the high water mark isn't the same as the buffer being full, only "nearly" full, as software handshaking isn't perfect, and some data can still come in after sending XOF due to any buffers between the sender's software and the receiver's hardware.

Related Topic