2

I want send and receive a 9 bit async-serial protocol with 4800 baud on my Arduino Uno, i have read on the specification from the ATmega328P that the uart can do that. My aim is that when my Uart receive the 9th bit as a 1 he must throw a interrupt. On this interrupt i can recognize that this byte was an adress byte. When he receive a zero he sould do nothing spezial, only transmit it as hex-byte over usb to the pc.

My Problem now, i can´t initialize the Uart right because the command Serial.begin(4800, config) is not enough, i must throw the interrupt and translate the data to hex-bytes. My Question can i modify the Serial.begin() source code respectively where can i find the source code for the Serial.begin function?

When there is no possibility to change the code has someone a other option for me to send and receive the 9 bit protocol with an Arduino Uno?

  • How are you connecting the the '328p's UART? I don't think you will get 9 bits through the '16u2 USB-serial chip on the Uno unless you modify its firmware, and you'd have to see how to get the USB side of things to support it. Your functional description isn't very clear either, but it sounds like you would need to modify the serial receive ISR away from the usual Arduino one. On the other hand, if what you want is for the Uno to be a bridge between some serial device and a PC, you will actually need to use and modify a software serial implementation or use a Leonardo instead of Uno. – Chris Stratton May 31 '16 at 14:55
5

If you want to set the UART to 9-bit mode, you will have to set the UCSZ02 bit of the _ucsrb register to 1 in HardwareSerial::begin(). For example:

void HardwareSerial::begin(unsigned long baud, byte config)
{
  // Mostly unchanged... but by the end:
  sbi(*_ucsrb, RXCIE0);
  cbi(*_ucsrb, UDRIE0);
  sbi(*_ucsrb, UCSZ02);  // set 9-bit data mode
}

Notice that you do not need to modify the Arduino core library for this: you could set that bit in your setup(), right after calling Serial.begin().

Then, in the HardwareSerial::_rx_complete_irq() interrupt handler, you will have to read the 9th bit as the RXB80 bit in UCSR0B, before reading the low byte from _udr (emphasis in the datasheet). For example, you could replace the line unsigned char c = *_udr; by:

bool is_address = UCSR0B & _BV(RXB80);  // read 9th bit first
unsigned char c = *_udr;                // then the other bits
if (is_address) {
  do_something_with_address(c);
  return;
}

where do_something_with_address() is the stuff you wanted to do in another interrupt (no need for that, you are already in interrupt context).

It is worth noting that, with an Arduino Uno, you will not be able to do all this while sending data to the PC. This is because the communication with the PC uses the only UART of the ATmega328P.

  • When i have insert a 1 in UCSZ02 what must i do with code? Must i patch my Arduino, or how can i add the bit at my Arduino? I didn´t know how i read the RXB80 bit as 9th bit have you a example for me pls. – sniffi May 31 '16 at 13:51
  • @sniffi: I added some examples of untested code to the answer. – Edgar Bonet May 31 '16 at 18:34
  • Can i use the Arduino mega 2560 for that? He has 4 uart´s or can i expand my Uno with a uart? – sniffi Jun 1 '16 at 5:35
  • 1
    I do not know about chips that could be used to add an UART to an Uno. They may exist, and if so they should be usable if they can be interfaced via I2C or SPI at 5 V. A Mega2560 is probably an easier solution. It's UART number 0 is used for communication with the host computer, so you can use any of the other 3 for your 9-bit protocol. Just make sure you tap into the correct registers, e.g. you set UCSZ12 and read RXB81 on UCSR1B if you use UART1. – Edgar Bonet Jun 1 '16 at 7:36
1

It sounds like you want some device with a 9-bit protocol to send data to an Arduino, and then the Arduino to forward that data (perhaps in a slightly different format) to a PC.

People who want to connect their Arduino to two serial devices at the same time (and the PC counts as one) generally either:

Change the hardware to accept multiple serial devices

While the Arduino Uno has only one hardware serial port, the following (and probably many others) have 2 or more hardware serial ports:

("Sending and Receiving 9-bit Frames with Arduino" uses the hardware approach).

Change the software to accept multiple serial devices

In principle, it's possible to tweak SoftwareSerial to handle 9-bit data. Several people have talked about it

1

The Max3140 is a very capable USART with built-in full/half-duplex RS-485 drivers that interfaces to a uController via SPI. They are a bit pricey and you would have to make a board, solder, etc..

Another solution would be to dedicate a simple and inexpensive minimal Arduino-compliant board (like a Pro-Mini) to interface with the "main" Arduino via I2C or SPI, and program the Pro-Mini for 9-bit addressing mode and add the RS-485 driver. Pro-Mini or Nano clones are dirt cheap, but it is not even that expensive to use an authentic Arduino product and support their great contributions ;-).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.