The Atmega supports 9 bit data, but the Arduino library doesn’t. Your only option using it (at least currently) is odd or even parity for the 9th data bit, there is no mark of space parity made available in via the library. This is a problem when communicating on say RS485 busses where mark and space parity is used as an address byte marker for instance, so that all the slaves on the bus can be interrupted check the address byte to see if its them and if not then ignore the remainder of the packet on the bus with the 9th bit set to the alternative state. The Atmega, like many microcontrollers, supports this, but the Arduino library doesn’t.

Ways to create 9 bit transmit data

Manipulate parity setting to give parity bit state you need

Transmit using flush() to wait while each byte is sent, and then altering the odd/even parity setting ahead of each byte to cause the parity to be the state you require for the 9th data bit you want. For mark parity you can also set parity to off and the number of stop bits to 2 (8N2). For space parity you must calculate the required odd/even parity setting to cause a space bit.

Bit bash

Bit bash your own transmit by disabling interrupts and manipulating the transmit pin at the required BAUD rate.

Change the microcontroller UART port setup
  //Atmeag2560 9 bit tx and receive example using Serial2.  Change every occurance of "2" to 0, 1 or 3 to use one of the other ports
  Serial2.begin(250000, SERIAL_8N1);
  while(!Serial2)
    ;
  //Change 8bit mode to 9bit mode (UCSZn1|UCSZn0 will already have been set to 11 by selecting 8N1, we just need to set UCSZn2 to change it to become 9N1
  UCSR2B |= 0x04;     //Bit4 of UCSR2B is the UCSZn2 bit

  //How to transmit a 9 bit byte
  Serial2.flush();      //Wait for last byte to have been sent
  UCSR2B |= 0x01;       //Write 9th bit.  Bit0 of UCSR2B is the 9th data bit (TXB8n), must be set or cleared before each byte is transmitted
  //UCSR2B &= ~0x01;
  Serial2.write(0x55);  //Write bits 7:0

  //Receiving 9 bit data will just occur as normal, but using this approach you simply won't be able to read the 9th bit (the 9th byte is written to RXB8n but it has to be read before each byte is read from UDRn, if you need to read it then you'll have to write your own receive handler).

Ways to create 9 bit receive data

Using standard library

There doesn’t seem to be a way to do this using the library without hacking it to access the ATmega registers directly. This has been done by people in the past but it seems there has never been enough demand to cause it to become a feature of the main library. If you use one of the odd/even parity settings you will miss all bytes which fail the parity setting as these will simply be dumped by the serial library.

Bit bash

Bit bash your own receive by disabling interrupts and monitoring the receive pin looking for the start bit and then timing and capturing each bit up to the stop bit.

Change the microcontroller UART port setup

See example in transmit section above

USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.

Comments

  1. carlos santos

    2 years ago

    super util la informacion

Comments

Your email address will not be published. Required fields are marked *