[Solved] 9 bit serial problem

Hi,

I'm experimenting a bit with using 9 bit serial using an Arduino Leonardo and IDE 1.8.3.

This is the code I have put together to test:

#include <SoftwareSerial.h>

#define BAUD 9600

SoftwareSerial mySerial(3, 4); // RX, TX

uint8_t n=0;

void setup() {
  
  // Open serial communications and wait for port to open:
  Serial.begin(BAUD);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
  //Serial1.begin(BAUD); //was used before replacement of files
  Serial1.begin(BAUD,true); //9 bit mode (used after replacement of hardware serial files)
  
  mySerial.begin(BAUD);

  Serial.println("READY!");
}

void loop() {
uint16_t indata=0;

  n = (n+1)%255;
  
  Serial.print("SS TX = ");
  if(n<=0x0F) Serial.print("0x0");
  else Serial.print("0x");
  Serial.print(n,HEX);

  mySerial.write(n);

  Serial.print(", S1 RX = ");
  
  while(Serial1.available()>0){
      indata = Serial1.read();

      if(indata<=0x000F) Serial.print("0x000");
      else if(indata<=0x00FF) Serial.print("0x00");
      else if(indata<=0x0FFF) Serial.print("0x0");
      else Serial.print("0x");
      Serial.println(indata,HEX);    
  }

  delay(500);

}

I ran it before replacing the libraries and it compiled and worked fine.

I then replaced the libraries with those from Nick's post (Mods to HardwareSerial to handle 9-bit data - Libraries - Arduino Forum) and now I am running into the following errors:

In file included from C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:30:0:

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial_private.h: In member function 'void HardwareSerial::_rx_complete_irq()':

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial_private.h:109:38: error: 'RXB80' was not declared in this scope

     unsigned int c = (*_ucsrb & bit (RXB80)) << 7;   // get the 9th bit (it's already shifted over one)

                                      ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\Arduino.h:123:25: note: in definition of macro 'bit'

 #define bit(b) (1UL << (b))

                         ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial_private.h:123:38: error: 'RXB80' was not declared in this scope

     unsigned int c = (*_ucsrb & bit (RXB80)) << 7;   // get the 9th bit (it's already shifted over one)

                                      ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial_private.h:123:33: note: in expansion of macro 'bit'

     unsigned int c = (*_ucsrb & bit (RXB80)) << 7;   // get the 9th bit (it's already shifted over one)

                                 ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp: In member function 'void HardwareSerial::_tx_udr_empty_irq()':

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:90:21: error: 'TXB80' was not declared in this scope

     *_ucsrb |= bit (TXB80);  // set 9th bit

                     ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\Arduino.h:123:25: note: in definition of macro 'bit'

 #define bit(b) (1UL << (b))

                         ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:92:22: error: 'TXB80' was not declared in this scope

     *_ucsrb &= ~bit (TXB80); // clear 9th bit

                      ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\Arduino.h:123:25: note: in definition of macro 'bit'

 #define bit(b) (1UL << (b))

                         ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp: In member function 'size_t HardwareSerial::write9bit(uint16_t)':

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:237:23: error: 'TXB80' was not declared in this scope

       *_ucsrb |= bit (TXB80);  // set 9th bit

                       ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\Arduino.h:123:25: note: in definition of macro 'bit'

 #define bit(b) (1UL << (b))

                         ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:239:24: error: 'TXB80' was not declared in this scope

       *_ucsrb &= ~bit (TXB80); // clear 9th bit

                        ^

C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\cores\arduino\Arduino.h:123:25: note: in definition of macro 'bit'

 #define bit(b) (1UL << (b))

                         ^

Using library SoftwareSerial at version 1.0 in folder: C:\Users\Diag 1\Downloads\Arduino v1.8.5\hardware\arduino\avr\libraries\SoftwareSerial 
exit status 1
Error compiling for board Arduino Leonardo.

Can somebody please help me understand why I am getting those errors an how to fix them. Thanks.

You need to define RXB80 somewhere. Or, since it is just the name of a bit number, use the actual number.

You don't need to use the bit() function either, as the result of the operation can be replaced with a constant.

Yes, thank you jreminton. I figured that much and after going thru some atmel datasheets I found out that RXB8 (or RXB80) is defined as bit1 in UCSRB register. I added the definition in HardwareSerial_private.h and it fixed the problem! :slight_smile:

It's a pity the library provided by Nick had that bug in it but thankfully it was a fairly easy fix!!! :smiley:

So I've been playing with the my code and I am seeing some weird stuff which I would be grateful if somebody could explain to me what going on!!! it's driving me crazy!!!

So this is the code I'm using:

#include <SoftwareSerial.h>

#define BAUD 9600

SoftwareSerial mySerial(3, 4); // RX, TX

uint8_t n=0;

void setup() {
  
  // Open serial communications and wait for port to open:
  Serial.begin(BAUD);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial1.begin(BAUD,true);
  // set the data rate for the SoftwareSerial port
  mySerial.begin(BAUD);

  Serial.println("READY!");
}

void loop() {
uint16_t indata=0;
  
  Serial.print("SS TX = ");
  if(n<=15) Serial.print("0x0");
  else Serial.print("0x");
  Serial.print(n,HEX);
  Serial.print(", ");
  
  mySerial.write(n);
  
  delay(500);

  n = (n+1)%256;
  
  Serial.print(Serial1.available());
  Serial.print(", S1 RX = ");
  while(Serial1.available()>0){
    Serial.print((int)Serial1.read(),HEX);   
  }
  Serial.println("");
}

and this is the output I am seeing:

READY!
SS TX = 0x00, 1, S1 RX = 0  //expecting 100
SS TX = 0x01, 1, S1 RX = 1  //expecting 101
SS TX = 0x02, 1, S1 RX = 2  //expecting 102
SS TX = 0x03, 1, S1 RX = 3  //expecting 103
SS TX = 0x04, 1, S1 RX = 4  //expecting 104
SS TX = 0x05, 1, S1 RX = 5  //expecting 105
SS TX = 0x06, 1, S1 RX = 6  //expecting 106
SS TX = 0x07, 1, S1 RX = 7  //expecting 107
SS TX = 0x08, 1, S1 RX = 8  //expecting 108
SS TX = 0x09, 1, S1 RX = 9  //expecting 109
SS TX = 0x0A, 1, S1 RX = A  //expecting 10A
SS TX = 0x0B, 1, S1 RX = B  //expecting 10B
SS TX = 0x0C, 1, S1 RX = C  //expecting 10C
SS TX = 0x0D, 1, S1 RX = D  //expecting 10D
SS TX = 0x0E, 1, S1 RX = E  //expecting 10E
SS TX = 0x0F, 1, S1 RX = F  //expecting 10F
SS TX = 0x10, 1, S1 RX = 10 //expecting 110
SS TX = 0x11, 1, S1 RX = 11 //expecting 111
SS TX = 0x12, 1, S1 RX = 12 //expecting 112
SS TX = 0x13, 1, S1 RX = 13 //expecting 113
SS TX = 0x14, 1, S1 RX = 14 //expecting 114
SS TX = 0x15, 1, S1 RX = 15 //expecting 115
SS TX = 0x16, 1, S1 RX = 16 //expecting 116
SS TX = 0x17, 1, S1 RX = 17 //expecting 117
SS TX = 0x18, 1, S1 RX = 18 //expecting 118
SS TX = 0x19, 1, S1 RX = 19 //expecting 119
SS TX = 0x1A, 1, S1 RX = 1A //expecting 11A
SS TX = 0x1B, 1, S1 RX = 1B //expecting 11B
SS TX = 0x1C, 1, S1 RX = 1C //expecting 11C
SS TX = 0x1D, 1, S1 RX = 1D //expecting 11D
SS TX = 0x1E, 1, S1 RX = 1E //expecting 11E
SS TX = 0x1F, 1, S1 RX = 1F //expecting 11F
SS TX = 0x20, 1, S1 RX = 0  //WATS GOING ON HERE!!!! expecting 120
SS TX = 0x21, 2, S1 RX = 1E1 //SHOULD BE ONLY ONE DATA AVAILABLE NOT 2!!! OUTPUTING 2 BYTES 0X01 AND 0XE1. expecting 121
SS TX = 0x22, 2, S1 RX = 1E2 //??
SS TX = 0x23, 2, S1 RX = 1E3 //??
SS TX = 0x24, 2, S1 RX = 1E4 //??
SS TX = 0x25, 2, S1 RX = 1E5 //??
SS TX = 0x26, 2, S1 RX = 1E6 //??
SS TX = 0x27, 2, S1 RX = 1E7 //??
//WIERD BEGAVIOUR CARRIES ON TO 0XFF. DATA READ BACK ON SERIAL1 NOT COHERENT WITH TX!?

the really weird thing is that it does not matter whether I set "Serial1.begin(BAUD,true);" to TRUE or FALSE; i'm getting the same output!

As mentioned in my first post I've replace the hardware serial files in the arduino folder with those provided by Nick for 9 bit serial communication.

Any help understanding this problem is most welcomed!

So after a bit on tinkering with the hardwareserial libraries, I managed to resolved the issue I was seeing. :smiley: ;D

please see library files attach. If you wish to used it, you would need to overwrite the original files. I HAVE NOT tested everything in the library so if you wish to use it please BACKUP the original files BEFORE you overwrite them.

Serialx.begin() has 2 argurments: baud [required] and config[optional], where x is your serial port used

default if config is not entered is 8 bit 1 stop bit.

To use 9 bit serial use the 9 bit definitions declared in hardwareserial.h
e.g to use 9 bit serial+ 1 stopbit at 9600baud, you would use Serialx.begin(9600, SERIAL_9N1);

HardwareSerial9bit.zip (7.57 KB)