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.