I am attempting to use 3 x TLC5917 chips to drive a row of LEDs in PWM. The LEDs share a common anode being powered through a transistor, with each LEDs cathode going to pins on the TLC5917 Chips.

There are obviously other chips specifically designed for PWM but my questions relate to the Arduino SPI Implementation.

The chips I am using are rated for 30MHz Max Speed. The Arduino (Uno) I am using runs at 16MHz. SPI can only run at half speed which means the SPI Transfer Max Speed for this hardware is 8MHz.

With this in mind, before overhead it should take 1/8Million seconds per clock cycle, equivalent to 1/8th of a Microsecond. This means that SPI should take 24 clock cycles to send out 24 bits. Clocking out all 3 bytes (24 bits) should take about 3 Microseconds before overhead. Then a few more microseconds to flip the latch pin.

Instead I see it taking about 12 Microseconds to send the 24 bits and another 12 Microseconds to latch the pin low and high, 4 times what I expected. Obviously there is some overhead but 400% seems excessive.

I have looked at the Arduino SPI Library to see if there is any obvious overhead but I cant see anything that would quadruple the theoretical transfer time.

This is the sketch I used to time the data transfers

#include <SPI.h>

void SSHigh(){
  PORTB = PORTB | 10000000;

void SSLow(){
  PORTB = PORTB ^ 10000000;

void setup() {
   pinMode(2, OUTPUT);
   digitalWrite(2, LOW);

void writeChips(byte red, byte green, byte blue){


long start;
long end;
long delta;

void loop() {

  start = micros();
  end = micros();
  delta = end - start;

  • There is always overhead, since the UNO doesn't have DMA. So it's waiting for the transfer the be completed, before it can send new data. This checking takes a few cycles, and doesn't always neatly align with the exact moment the transfer is done. There might also be overhead from the function call, and the return value, but the compiler might inline all the code. It might be useful to look at the compiled assembly code, to see what's going on. – Gerben Sep 25 '18 at 10:01
  • 1
    Is there any way we can meaningfully reduce the overhead without having access to DMA? – Zano Sep 25 '18 at 10:05
  • 1
    I have already achieved PWM using an interupt like you suggested. I was looking to gain further PWM bits, but at this point I am limited by SPI Speed (or the Arduino implementation of it). – Zano Sep 25 '18 at 10:17
  • 1
    Crap, your right. Setting it to DIV_2 bring it down to about 8 Microseconds. The rest must be overhead. – Zano Sep 25 '18 at 10:38
  • 1
    PS I've done some software PWM on shift registers in the past, using a timer to update all the shift registers. I used one of the PWM outputs of that same timer to connect to the enable pin on the shift registers. That way I could set a global brightness on all the leds, while at the same time having software-PWM on all the individual leds. I used that to change the brightness of the display depending on the ambient brightness, without sacrificing any resolution in individual PWM. – Gerben Sep 25 '18 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.