Bridge Between USART0 and USART1 - Arduino Mega 2560

Hi,

I want to build a bridge that receive byte on USART0( USB) and put this byte on USART1 (Serial sensor) and vice versa. This on my Arduino Mega 2560.

I think to write a sketch that use USART Interrupts on the received byte.

The interrupt occur when i receive a byte and forward this byte on the other USART:

USART0 --> USART1
USART1 --> USART0

I have a problem in the callbacks code; in particular in the code that forward the byte.

This is my sketch.

#include <avr/interrupt.h> 
#include <avr/io.h> 

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


#define RTS                   4
#define CTS                   5
#define CONFIG                3
#define RESET                 2

//Define Bridge GPIO
#define PIN_BRIDGE_MODE       22 
#define PIN_SAK_MODE          23

//Define USARTs
unsigned long baud = 192000;    
unsigned long clockspeed = F_CPU; /* F_CPU is a predefined constant equal to the clock speed of the microcontroller.
                                     for the Arduino duomilanove it is 16000000.*/
unsigned long baudPrescale;       /* The baud prescale that will be loaded into the 
                                     UBRR0H and UBRR0L registers to set the USART baud rate */

//#define UBRR_VALUE 51 // --> UBBR = 51 => BAUD_RATE  19200

volatile byte ReceivedByteUSART0 = 0; 
volatile byte ReceivedByteUSART1 = 0; //holds the incoming byte from the receive buffer.

void setup()
{
   pinMode(13,OUTPUT);
   cli();  //disable interrupts while initializing the USARTs
   baudPrescale = (((clockspeed / (baud * 16UL))) - 1);

   //                                             Initialize USART0 
   //
   UBRR0H = (uint8_t)(baudPrescale>>8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 
   UBRR0L = (uint8_t)baudPrescale;       // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 
   
   /* set transfer complete flag (TXC0 = 1).
   *  clear Frame Error flag (FE0 = 0).   
   *  clear Data overrun flag (DOR0 = 0).
   *  clear Parity overrun flag (UPE0 = 0).
   *  disable doubling of USART transmission speed (U2X0 = 0).  
   *  Disable Multi-Processor Communication Mode-- whatever that is. (MCPM0 = 0)  */ 
   sbi(UCSR0A, TXC0);
   cbi(UCSR0A, FE0);
   cbi(UCSR0A, DOR0);
   cbi(UCSR0A, UPE0);
   cbi(UCSR0A, U2X0); 
   cbi(UCSR0A, MPCM0);
   
   /* Enable Receive Interrupt (RXCIE0 = 1).
   *  Disable Tranmission Interrupt (TXCIE = 0).
   *  Disable Data Register Empty interrupt (UDRIE0 = 0). 
   *  Enable reception (RXEN0 = 1).
   *  Enable transmission (TXEN0 = 1). 
   *  Set 8-bit character mode (UCSZ00, UCSZ01, and UCSZ02 together control this, 
   *  But UCSZ00, UCSZ01 are in Register UCSR0C). */  
   sbi(UCSR0B, RXCIE0);
   cbi(UCSR0B, TXCIE0);
   cbi(UCSR0B, UDRIE0);
   sbi(UCSR0B, RXEN0);
   sbi(UCSR0B, TXEN0);
   cbi(UCSR0B, UCSZ02);
   
  /* USART Mode select -- UMSEL00 = 0 and UMSEL01 = 0 for asynchronous mode.
   *  disable parity mode -- UPM00 = 0 and UPM01 = 0. 
   *  Disabilitato: Set USBS = 1 to configure to 2 stop bits per DMX standard.  The USART receiver ignores this 
   *  setting anyway, and will only set a frame error flag if the first stop bit is 0.  
   *  But, we have to set it to something.
   *  Finish configuring for 8 data bits by setting UCSZ00 and UCSZ01 to 1.  
   *  Set clock parity to 0 for asynchronous mode (UCPOL0 = 0). */   
   cbi(UCSR0C, UMSEL00);
   cbi(UCSR0C, UMSEL01);
   cbi(UCSR0C, UPM00);
   cbi(UCSR0C, UPM01);
   cbi(UCSR0C, USBS0);
   sbi(UCSR0C, UCSZ00);
   sbi(UCSR0C, UCSZ01);
   cbi(UCSR0C, UCPOL0);
   
   //                                             Initialize USART1 
   //
   UBRR1H = (uint8_t)(baudPrescale>>8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 
   UBRR1L = (uint8_t)baudPrescale;       // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 
   
   /* set transfer complete flag (TXC0 = 1).
   *  clear Frame Error flag (FE0 = 0).   
   *  clear Data overrun flag (DOR0 = 0).
   *  clear Parity overrun flag (UPE0 = 0).
   *  disable doubling of USART transmission speed (U2X0 = 0).  
   *  Disable Multi-Processor Communication Mode-- whatever that is. (MCPM0 = 0)  */ 
   sbi(UCSR1A, TXC0);
   cbi(UCSR1A, FE0);
   cbi(UCSR1A, DOR0);
   cbi(UCSR1A, UPE0);
   cbi(UCSR1A, U2X0); 
   cbi(UCSR1A, MPCM0);
   
   /* Enable Receive Interrupt (RXCIE0 = 1).
   *  Disable Tranmission Interrupt (TXCIE = 0).
   *  Disable Data Register Empty interrupt (UDRIE0 = 0). 
   *  Enable reception (RXEN0 = 1).
   *  Enable transmission (TXEN0 = 1). 
   *  Set 8-bit character mode (UCSZ00, UCSZ01, and UCSZ02 together control this, 
   *  But UCSZ00, UCSZ01 are in Register UCSR0C). */  
   sbi(UCSR1B, RXCIE0);
   cbi(UCSR1B, TXCIE0);
   cbi(UCSR1B, UDRIE0);
   sbi(UCSR1B, RXEN0);
   sbi(UCSR1B, TXEN0);
   cbi(UCSR1B, UCSZ02);
   
  /* USART Mode select -- UMSEL00 = 0 and UMSEL01 = 0 for asynchronous mode.
   *  disable parity mode -- UPM00 = 0 and UPM01 = 0. 
   *  Set USBS = 1 to configure to 2 stop bits per DMX standard.  The USART receiver ignores this 
   *  setting anyway, and will only set a frame error flag if the first stop bit is 0.  
   *  But, we have to set it to something.
   *  Finish configuring for 8 data bits by setting UCSZ00 and UCSZ01 to 1.  
   *  Set clock parity to 0 for asynchronous mode (UCPOL0 = 0). */   
   cbi(UCSR1C, UMSEL00);
   cbi(UCSR1C, UMSEL01);
   cbi(UCSR1C, UPM00);
   cbi(UCSR1C, UPM01);
   cbi(UCSR1C, USBS0);
   sbi(UCSR1C, UCSZ00);
   sbi(UCSR1C, UCSZ01);
   cbi(UCSR1C, UCPOL0);
      
   
   
   //Enable Interrupts
   sei();  // Load upper 8-bits of the baud rate value into the high byte of the UBRR register .
   
    //                                          Configure GPIO
    pinMode(RESET,OUTPUT);
    pinMode(CONFIG,OUTPUT);
    pinMode(RTS,OUTPUT);
    pinMode(CTS,OUTPUT);
    //Configure Bridge GPIO
    pinMode(PIN_BRIDGE_MODE,INPUT);
    pinMode(PIN_SAK_MODE,INPUT);   
    
    // Delay before enable Radiocraft Modem
    delay(100);
    
    digitalWrite(RESET,HIGH);
    digitalWrite(CONFIG,HIGH);
}

void loop()
{

}


//Interrupt Callback USART0 RX
ISR(USART0_RX_vect)
{  
  //digitalWrite(13,HIGH);
  ReceivedByteUSART0 = UDR0;  //The receive buffer (UDR0) must be read during the reception ISR, or the ISR will just 
                              // execute immediately upon exiting. */                           
}

//Interrupt Callback USART1 RX
ISR(USART1_RX_vect)
{  
  ReceivedByteUSART1 = UDR1;
}

In my sketch i configure the USARTs registers and i configure interrupt on the received byte.

Trough the led on pin13 I can test the callback functionality. In fact when i send a byte on USART0 the led blinks. This mean that the callback works.

My problem is: which code I have to write in each callback to put the received byte on the other USART?

For example: I receive a byte on USART0 and I want to put this byte on USART1.

ISR(USART0_RX_vect)
{  
 
  ReceivedByteUSART0 = UDR0;  // Store the received byte in a volatile variable
  
  ???.... which code for put the byte on USART1 ... ????
                                                 
}

I think that I have to use low level function into the callback.

For a test I insert Serial1.write() into the ISR(USART0_RX_vect) callback but the compiler give me an error.

Could anyone help me?

Thanks in advance!

This typical something to ask in the avrfreaks.net forum, or perhaps on the Atmel forum.
You can find many USART and UART examples in the "Projects" section at avrfreaks.net.

Do you want a bridge using low level programming ?
You could use the Arduino functions with the buffers and interrupts that are used inside the Serial library.

About your question, sorry, I have made serial functions using low level programming in the past, but it's too long ago. Never needed it, since I started using Arduino.

This will echo the input of the serial ports to the output of the other.

void setup ()
{
  
  Serial.begin ( 9600 ); 
 
  Serial1.begin ( 9600 );
 
} // setup

void loop ()
{
  
  while ( Serial1.available () )
  { 
    Serial.write ( Serial1.read () );   
  }
   
  while ( Serial.available () )         
  {
    Serial1.write ( Serial.read () );  
  }
  
} // loop

Peter_n:
This typical something to ask in the avrfreaks.net forum, or perhaps on the Atmel forum.
You can find many USART and UART examples in the "Projects" section at avrfreaks.net.

Do you want a bridge using low level programming ?
You could use the Arduino functions with the buffers and interrupts that are used inside the Serial library.

About your question, sorry, I have made serial functions using low level programming in the past, but it's too long ago. Never needed it, since I started using Arduino.

Thanks for your reply.

I post my question on avrfreaks.

I will let you now.

tf68:
This will echo the input of the serial ports to the output of the other.

void setup ()

{
 
 Serial.begin ( 9600 );

Serial1.begin ( 9600 );

} // setup

void loop ()
{
 
 while ( Serial1.available () )
 {
   Serial.write ( Serial1.read () );  
 }
 
 while ( Serial.available () )        
 {
   Serial1.write ( Serial.read () );  
 }
 
} // loop

Really? It's so simple?

Do I do nothing else?

I try a similar code but it seems not routing the byte.

Do you try this code?

Thanks for the reply

That is how it is done with the Arduino Serial library. What was your code ?
If you don't have a very specific timing request, you can use the Serial library. Using the low-level programming with registers would also require debugging.

Perhaps you have a hardware problem ? Sometime RX needs to be connected to a module with the label 'TX', but sometime it is labeled 'RX'. Sometimes the signal is RS-232 with high voltages and inverted signal, sometime the serial signal is 5V TTL level and still inverted. Some devices accept 0 and 5V TTL level signal, other don't. Some devices ... well... I can go on and on about what can go wrong with baudrates and non-standard databits and ground paths and blown Arduino pins, bad breadboard connections, and so on.

Yes, that code should work fine. I have used very similar code as a bluetooth test. You even have time for some simple processing. As far as it not working, do you have the baud rates set correctly?