suggestion on shiftout implementation

My current project calls shiftOut() potentially at 1ms intervals and hope it would take as little time as possible. I tried these codes and found to be faster by >10% in time when tested with LSBFIRST.

if (bitOrder == LSBFIRST) {
digitalWrite(dataPin, val & 0x01);
val >>= 1;
else {
digitalWrite(dataPin, !!(val & 0x80));
val <<= 1;

If you really want it to take as little time as possible, use SPI.transfer() & take advantage of the built in hardware shift register. With SPI divisor set at 2, 8 MBit transfers can occur, so a byte can go out in just about 1uS.

check my exploration - -

Thanks for pointing to SPI. Some background to my current project.

My project interfaces 2 cascaded STP16CP05 to drive four 7-seg LED modules. The main program uses shiftOut() to send 4 bytes of data to update the display. I had serious problem when I used PWM at D5 (timer 0) to control brightness through the OE pins. Display kept corrupted when I do that.

I did not use SPI as STP16CP05 does not have SS pin. Furthermore the project needs to do SPI with NRF24L01+. (May be I still can use SPI as long as I pulse the SLE pin of STP16CP05 only after writing data to it, ignoring any other SPI traffic.)

Due to the problem with PWM, I resort to use MsTimer2 to control brightness. With the OE permanently low (no PWM), the MsTimer2 ISR calls shiftOut() with the worst case of 1ms interval for different brightness. It works fine. But I wished to avoid this method as I also wish to use tone() function that also use timer2.

As the shiftOut() is now done in ISR, I wish to ensure that it takes as little time as possible. The original library took about 0.48ms to send 4 bytes on ATMega328P running 16MHz. The version above took about 0.42ms. I thought it was significant and shared it.

Anyway, I managed to get hold of two TLC5928 which has identical pin as STP16CP05 (but lower max current & is more than enough for the project). I am really glad that it works perfectly with PWM at its BLANK pin (or OE pin for STP16CP05). I now no longer need to use MsTimer2 !

I do have one concern if I do use SPI in MsTimer2 ISR. Formerly I had another project that tried to use library i2c functions in MsTimer2 ISR. It gave problems. Not sure if using SPI library in MsTimer2 ISR will also give problem.

Anywhere, my current problem is solved using the TLC5928. Thanks.

Update (24 Feb 14): To my disappointment, looks like TLC5928 constant current control is not so good. When I do brightness control using either PWM or using timer2ISR with shiftOut(), the decimal point brightness is significantly brighter compared to other segments. I believe this is due to its lower Vf compared to other segments. This is not the case for STP16CP05.

Looks like I have to go back to use STP16CP05 using timer2ISR & shiftOut() (may be SPI if it works) and forget about the use of PWM.

Update 8 Apr 14: Tried and confirmed that STP16CP05 works with SPI. Unfortunately, as SPI function now need to be called by timer ISR and also the main program (communicating with nrf24L01+), it gives rise to new problem due to non-reentrancy of the use of SPI hardware resource. I need to revert back to shiftOut() called by timer ISR.