Go Down

Topic: Hardware SPI: how to shift out less than 1 byte? (Read 937 times) previous topic - next topic


Hello everyone.
I'm interfacing 12-bit Serial DAC (DAC8512), and it seems from datasheet that it expects exactly 12 bits of data clocked in by SPI bus.

Clocking out 12 significant bits and then 4 zeroes (8+8 bits) results in weird waveform on my scope.

So I'm just curious: is it possible to clock out exactly 12 bits?


is it possible to clock out exactly 12 bits?

Not with the hardware SPI.
You will have to bit bang the signals to get your 12 bits.


Did you try putting the 4 zeroes BEFORE your data?  SPI devices often take the last N bits.

An alternative is to use software SPI but that will be relatively slow.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e


John is right much easier to send it as an int and mask off the unwanted bits.

--> WA7EMS <--
"The solution of every problem is another problem." -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

Nick Gammon

Judging by the datasheet you can send 12 bits followed by a few "don't care":


The 74HC161 counter in incremented on every rising edge of the clock. Additionally, the data is loaded into the DAC8512 on the falling edge of the clock by inverting the serial clock using gate "Y." The timing diagram shows that after the twelfth bit has been clocked the output of the counter is binary 1011. On the very next rising clock edge, the output of the counter changes to binary 1100 upon which the output of gate "X" goes LOW to generate the LD pulse. The LD signal is connected to both the DAC's LD and the counter's LOAD pins to prevent the thirteenth rising clock edge from advancing the DAC's internal shift register. This prevents false loading of data into the DAC8512.

I would be very surprised if modern designers expected exactly 12 bits. More like 16 bits with a provision to ignore some of them, as the above seems to state.

Nick Gammon

If I'm wrong (and I've been wrong before ;)  ) here is some code for bit-banged SPI:


You would need to adapt it a bit to do 12 bits.


johnwasser, thanks, that resolved some issue, but now other problem occurs.

Here is my code:
Code: [Select]

//Init SPI


for (int b=0;b<4095;b++)
//Prepare to output 2 bytes: SPI CS assert LOW, DAC latch set high.


//  send in the value via SPI:
SPI.transfer((b>>8));  // High byte
SPI.transfer((b&0xFF)); //Low byte

//Assert CS low

//Now set the DAC to load register to output (LD Low->High).

delayMicroseconds(10);//Set a delay to simplify scope analysis
delay(200); //200ms delay between cycles

The DAC is 12-bit, so, by datasheet, should get values between 0 and 4095. When we send some zeroes before valuable data, the DAC input shift register just shifts that zeroes to the left out of register, so only 12 bits remain.

That code is supposed to go from 0 to 4095, resulting in 0-to-4.095V "saw" with delay between each cycle.

The problem is that DAC seems to read only 11 bit, so I get not single "saw", but a double "saw". Attached is info from my scope:

So I'm curious: Does the SPI send something other than my 2 bytes to line? Maybe some control bits between each of my byte?


Solved. Changing SPI to MODE3 instead of MODE0 helped.
However, it seems to me that MODE0 is the right mode, according to datasheet.

Nick Gammon

Page 4 of the datasheet shows the clock normally high, so modes 2 or 3 would be appropriate.

Then the first diagram on that page shows the sampling of D11 on the leading edge, so it seems to me that mode 2 is possibly more correct.


Jun 17, 2013, 09:57 am Last Edit: Jun 17, 2013, 10:52 am by SurferTim Reason: 1

Solved. Changing SPI to MODE3 instead of MODE0 helped.
However, it seems to me that MODE0 is the right mode, according to datasheet.

Not the way I see it. Page 4 of the datasheet says clock is HIGH with LOW pulses (CPOL=1) and captures on the rising edge and propagates on the falling edge (CPHA=1).
That is mode 3.

edit: Here is how to compute mode. The phase (CPHA) isn't based on rising or falling edge as I might have implied above, but first or second edge after the slave select is activated (LOW).

If clock is LOW with HIGH pulses, then CPOL = 0.
If clock is HIGH with LOW pulses, then CPOL = 1.

If it captures on the first edge (rising or falling) after SS goes LOW, then CPHA=0
If it captures on the second edge (rising or falling) after SS goes LOW, then CPHA=1



Go Up