Issue with 16-bit ADC (ADS8354) communication with Teensy 4.1


New member
Hello everyone,

I’m currently working on a part of a big project that requires me to read the converted digital signals from an ADC (ADS8354 - ). I know the Teensy 4.1 has a 12-bit ADC feature but the project requires a resolution of 16-bit which is why I’m opting to use the ADS8354. The issue I’m facing right now is that I’m only able to get values of 1 as output. I’m writing a simple sketch to get the converted digital values and printing out the 16-bit values on the serial monitor (which I’ve attached below). I’m not sure if there’s an issue with my code, SPI setting, ADC settings or the wiring of my ADC.

I’ve been able to use the decode function on my oscilloscope to see the MISO line from the ADC to the Teesny and I’m able to see some HEX values. Not sure if those are the correct values just yet though.

I suspected that the issue might be because the Teensy 4.1 is too fast for the ADC but I also tried adding some delays in my code and even using a Teensy 3.2 but I’m still facing the same issue.

I also tried using SPI_MODE1 but that still didn’t fix my issue.

These are my current pin assignments:
CS on the ADC = pin 10 on teensy
SCLK on ADC = pin 13 on teensy
SDI on ADC = pin 11 on teensy
SDO on ADC = pin 12 on teensy
GND on ADC = GND on teensy

Arduino code:
#include <SPI.h>

const int CS_PIN = 10; // Chip Select pin for the ADC

void setup() {
// Initialize serial communication

// Initialize SPI
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE3));
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);

uint16_t config_command = 0x8040; // Configure the ADS8354 for full range +-Vref and internal reference
digitalWrite(CS_PIN, LOW);
digitalWrite(CS_PIN, HIGH);


void loop() {

// Read the converted data
digitalWrite(CS_PIN, LOW);
uint16_t adc_data = SPI.transfer16(0x0000);

digitalWrite(CS_PIN, HIGH);
Serial.print("ADC Raw: ");
Serial.println(adc_data, HEX);
// Add a small delay to avoid overwhelming the serial monitor

ADC Raw: 1
ADC Raw: 1
ADC Raw: 1
ADC Raw: 1
ADC Raw: 1
ADC Raw: 1
ADC Raw: 1

this is a graph of the differential input that I'm trying to convert:
Not sure if it matters but I'm missing SPI.endTransaction(); while using SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE3));.

Not sure if it matters but I'm missing SPI.endTransaction(); while using SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE3));.

Hi Paul
I did try adding SPI.endTransaction() at the end of the loop but that also didn't work.
In the TI datasheet, the term SPI is carefully avoided...
Not immediately clear what SPI mode is to be used. Sampling SDI on the falling edge, and clocking out SDO on the same falling edge. Then it's key you make sure that on the Teensy side the output pin for SCLK was already output, or at least pulled high, before the SPI "start transaction" is called.
Also the datasheet suggests that SDI B15 must be set and must be stable BEFORE /CS falls...

But also take note of this:

With SDI B15 cleared (the first bit read in after CS goes low), the first 16 bits that you will read from SDO are all zero. The ADC then is busy doing its A/D Convert job. Only the next 16 bits will get you the sample data that you're after... If you only read 16 bits while CS is low, then...

Did you find resolution to this?
I have been playing with ADS8354 recently, and I was stuck on the same steps as you. From what I read on TI forums, it seems that ADS8354 doesn't follow SPI modes accurately.
For writing to ADS8354 you should be using SPI Mode 1 and for reading SPI Mode 3 as how data is sampled on SDI and SDO is different when you take host controller into account.

Please refer to this:

Please let me know if you find resolution.
I ran into some issues with SPI timing a few years ago. Here is one of the posts where it wax discussed:
SPI MOSI pulled low too late on Teensy 4.0

Perhaps the ADS8364 has a similar sensitivity to SPI timing.
I just checked the SPI.begintransaction code and it seems that the clock delay has been incorporated into the TD1.59 version of the SPI library.

LPSPI_CCR_PCSSCK(div/2) has been added to the SPI _csr setup value.

Perhaps, if the SPI clock is 20MHz, (div/2) does not provide enough delay. In my tests in 2020, I hard-coded LPSPI_CCR_PCSSCK(128) for a large delay to solve some problems.