9 Bit Serial on Teensy 3.1

Status
Not open for further replies.

iwalker

New member
Hi All

Moving on from Arduino to Teensy 3.1 and Teensyduino.
I need to talk to a serial device (slot machine) that uses a rather strange serial packet structure. It needs 9 bits where the 9th bit acts as a wake up bit to tell the device that it is being addressed.

On Arduino I used the code suggested by Nick Gammon in this post - http://forum.arduino.cc/index.php?topic=54120
Code:
void SASPoll()
{
  UCSR0B = 0b10011101;  // turn 9th bit on
  Serial.write(SASAdr);
  UCSR0B = 0b10011100;  // turn 9th bit off 
}

How do I go about achieving the same functionality by directly manipulating the serial control register for Teensy 3.1
(It looks like I need to enable 9 bit at bit 4 of UART C1 register and then change it to 1 or 0 by writing to bit 7 of the UART C3 register)

I have seen this post in the forum - http://forum.pjrc.com/threads/23873-serial-9-bit-on-the-t3?highlight=parity but still not to clear how I can achieve above.

TIA
Ian
 
Last edited:
Teensy 3.1 has 9 bit support, but it's not enabled by default, because it increases memory usage. You first need to uncomment this line in HardwareSerial.h.

https://github.com/PaulStoffregen/cores/blob/master/teensy3/HardwareSerial.h#L36

After editing that line, you can use 9 bit mode with Serial1.begin(baud, SERIAL_9N1);

Ordinary Serial1.print() and Serial1.write() will send data with the 9th bit cleared to zero. To send bytes with all 9 bits, use Serial1.write9bit().

Details are on this page:

http://www.pjrc.com/teensy/td_uart.html

In 9 bit mode, Serial1.read() will return 0 to 511 (instead of 0 to 255), or -1 if no data.
 
If you *really* want to use an ugly hack, like that code AVR register code, the corresponding register on Teensy 3.1 is "UART0_C3".

It's documented in section 47.3.7 on page 1218 of the reference manual.

http://www.pjrc.com/teensy/K20P64M72SF1RM.pdf

However, I do NOT recommend using that terrible hack. Even in AVR-based Arduino, it's trouble just waiting to happen.

Teensy 3.1 has well supported 9 bit communication, so just uncomment that line to enable it, and use Serial1.write9bit(), for a very reliable solution.
 
Thanks Paul - Working nicely on all 3 serial channels.

If you *really* want to use an ugly hack, like that code AVR register code
Why is direct register access considered a ugly hack ?
Even in AVR-based Arduino, it's trouble just waiting to happen
What can go wrong doing it this way ?.
Can anybody advise a better solution for the Arduino platform.

Thanks Again
 
Why is direct register access considered a ugly hack ?

#1: You might write at the wrong moment, since your code has no visibility into the interrupt timing. Even if it works now, later when you or someone else works with the code, it's a timing disaster just waiting to happen.

#2: It's specific to only 1 type of chip, and only certain models within that line of chips.

Can anybody advise a better solution for the Arduino platform.

Switching to Teensy would be my suggestion! :D

The Arduino devs have considered 9 bit mode several times. They're not actively working on it, and so far the pull requests people have submitted had problems. They tentatively decided to use the same API as Teensyduino (quite a number of features start in Teensy and eventually get ported back to regular Arduino), so odds are good it'll someday come to Arduino, when/if someone goes through the effort of submitting a pull request they're willing to merge.
 
I am so confused. How do I enable SERIAL_9N1 with Teensy 3.6 Editing the HardwareSerial.h does nothing. where is the file I need to edit located? It is not the one I have in Libraries, it does nothing.
 
If my memory is correct, you need to edit HardwareSerial.h and uncomment the line: //#define SERIAL_9BIT_SUPPORT

Assuming Serial1 for example, I believe you would then do something like:
Serial1.begin(115200, SERIAL_9N1);
 
Thanks. My problem is that editing HardwareSerial.h does nothing. and it seems the HardwareSerial.h I am editing in fact is not in use, and I have no idea where to find the HardwareSerial.h that is in use. It is not the one in Library.

I use Mac, was testing with Arduino 1.6.12, just updated to 1.8.3

If my memory is correct, you need to edit HardwareSerial.h and uncomment the line: //#define SERIAL_9BIT_SUPPORT

Assuming Serial1 for example, I believe you would then do something like:
Serial1.begin(115200, SERIAL_9N1);
 
This is what I have in HardwareSerial.h

// uncomment to enable 9 bit formats
#define SERIAL_9BIT_SUPPORT

it is saved and I have tested this is the one that show on Arduino include library, so it should be loaded. But it just does not work.

It mentions a bit further down

// Teensy LC and 3.5 and 3.6 Uarts have 1/2 bit stop setting
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
#define SERIAL_2STOP_BITS 0x100
#define SERIAL_8E2 (SERIAL_8E1 | SERIAL_2STOP_BITS)
#define SERIAL_8O2 (SERIAL_8O1 | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV (SERIAL_8E1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV (SERIAL_8O1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_TXINV (SERIAL_8E1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_TXINV (SERIAL_8O1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV_TXINV (SERIAL_8E1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV_TXINV (SERIAL_8O1_RXINV_TXINV | SERIAL_2STOP_BITS)
#endif

Is that over rooling the previous settings for Teensy 3.6, and this does not include 9 bit.
 
I am not an expert on this stuff, but have tried to help out and fix a few things earlier. And did add some of the above I believe during the T3.6 beta stuff.

So hopefully someone who makes use of this can answer this better than I can.

The extra defines you mentioned were added as some of the newer boards (T-LC and 3.5 and 3.6) not only allow the code to use 9 data bit mode, they also allow the users code to optionally use 2 stop bits... Most of the above simply give you a whole variety of different versions of it, where you can choose Parity (Odd, Even, NONE) and you can turn on Inverting the TX and/or RX signals...

But in addition you should still have simple 9 data bit mode...

Also not much to go on here... As you have not provided any code, to know what it is you are actually trying to do. Also have not fully stated, when I execute this code I expected to see X, but instead I see Y... So again not sure what else I can say
 
No matter what I do, I only get

Arduino: 1.8.3 (Mac OS X), TD: 1.37, Board: "Teensy 3.6, Serial, 180 MHz, Faster, US English"

Build options changed, rebuilding all
HoverBoard_Control: In function 'void setup()':
HoverBoard_Control:9: error: 'SERIAL_9N1' was not declared in this scope
Serial1.begin(26315, SERIAL_9N1);
^
'SERIAL_9N1' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
 
Here is the code, The code works if I set SERIAL_8N1 (but communication does not) with SERIAL_9N1 I get the above error



void setup() {
Serial1.begin(26315, SERIAL_9N1);
Serial.begin(115200);
}

char c = ' ';
signed int sp=0;

void loop() {
Serial.println(c);
if(c == ' ') {
sp=0;
} else if(c == 'q') {
sp -= 10;
} else if(c == 'w') {
sp += 10;
} else if(c == '2') {
sp += 100;
} else if(c == '1') {
sp -= 100;
}
Serial.print("speed ");
Serial.println(sp);
Serial.print(" low byte ");
Serial.print((sp & 0xFF), HEX);
Serial.print(" high byte ");
Serial.println((sp >> 8) & 0xFF, HEX);
do {
Serial1.write9bit(256);
Serial1.write9bit(sp & 0xFF);
Serial1.write9bit((sp >> 8) & 0xFF);
Serial1.write9bit(sp & 0xFF);
Serial1.write9bit((sp >> 8) & 0xFF);
Serial1.write9bit(85);
delayMicroseconds(300);
} while(!Serial.available());
c=Serial.read();
}
 
I just think the HardwareSerial does not get used because even when I comment out SERIAL_8N1 it compiles ok with Serial1.begin(26315, SERIAL_8N1);

#define SERIAL_7O1 0x03
//#define SERIAL_8N1 0x00
#define SERIAL_8N2 0x04
 
I built the program you mentioned on 1.8.2 with the 9 bits enabled.
Code:
void setup() {
  Serial1.begin(26315, SERIAL_9N1);
  Serial.begin(115200);
}

char c = ' ';
signed int sp = 0;

void loop() {
  Serial.println(c);
  if (c == ' ') {
    sp = 0;
  } else if (c == 'q') {
    sp -= 10;
  } else if (c == 'w') {
    sp += 10;
  } else if (c == '2') {
    sp += 100;
  } else if (c == '1') {
    sp -= 100;
  }
  Serial.print("speed ");
  Serial.println(sp);
  Serial.print(" low byte ");
  Serial.print((sp & 0xFF), HEX);
  Serial.print(" high byte ");
  Serial.println((sp >> 8) & 0xFF, HEX);
  do {
    Serial1.write9bit(256);
    Serial1.write9bit(sp & 0xFF);
    Serial1.write9bit((sp >> 8) & 0xFF);
    Serial1.write9bit(sp & 0xFF);
    Serial1.write9bit((sp >> 8) & 0xFF);
    Serial1.write9bit(85);
    delayMicroseconds(300);
  } while (!Serial.available());
  c = Serial.read();
}
And it compiled just fine...
I did not try on my 1.8.3 version yet as my current code has all of the Serial objects from one object... Which is not part of build...

Yes T3.6 supports 9 bit mode. Look at chapter 59 in reference manual... (Or chapter 62 for Serial6)
Look at register UARTx_C1 register for M bit that controls 8 bit or 9 bit. Also other bits for parity...
 
But where is this stuff I need to modify? where is it located on Mac?

Buting the hardwareserial.h to arduino/libraries does not work and I can not find it anywhere. I just installed the 1.8.3 and Teesny environment on it.
 
Last edited:
Finally I found it. On Mac the files that need to be edited are not to be found with the find functionality, they are located under the Arduino icon, right click and select 'Show package content'

The path is strange I think: Contents/Java/Hardware/Teensy/Avr/Cores/Teensy3/HardwareSerial.h .

It only took me 4 hours to figure this out, Hopefully it helps someone.
 
I am not much of a MAC person, but I have one I use for secondary stuff. Not sure how you are setup...
But for example I use sublimetext 3 on my different computers including the MAC.

Example I have a version of Arduino in my Applications folder. So if I open up the Applications/Arduino.app in Sublime Text,

There is a file structure, that looks something like:
Arduino.app/contents/Java/hardware/teensy/avr/cores/teensy3

(may have mistyped exact name here... Should double check file name cases)...
In that folder is HardwareSerial.h
 
Thanks KurtE, I finally found it as mentioned above. I never looked under Java, do not understand why it is there? anyway problem solved.
 
Somewhat related to this I discovered that when using Serial1 on Teensy LC with SERIAL_8N2 it gets configured for 9 bits, 1 stop bit (config value: 0x04) so I do get 11 bits total, but just one stop bit. The correct config value to get 8N2 is 0x100, similar to the 8E2, 8O2 modes that already get special attention in HardwareSerial.h. This issue also affects the 8N2 RXINV/TXINV modes.
 
Finally I found it. On Mac the files that need to be edited are not to be found with the find functionality, they are located under the Arduino icon, right click and select 'Show package content'

The path is strange I think: Contents/Java/Hardware/Teensy/Avr/Cores/Teensy3/HardwareSerial.h .

It only took me 4 hours to figure this out, Hopefully it helps someone.

Perhaps we might see the Teensy related files one day in ~user/Library/Application Support/Teensyduino ? Seems more logical to me and would ease their inclusion from other IDEs, too.
 
Status
Not open for further replies.
Back
Top