How can I SPI "Latch" (LE/CS/SS) for a specific number of SCLK cycles?

Context

I am working on a project which includes 13 cascaded STMicroelectronics LED1642GWs. These LED drivers are essentially 16bit shift registers, whereby the buffered serial data can be loaded to a number of different registers dependant on the required function.

The function is selected through the use of "digital keys", which is selected by number of CLK cycles for which the LE (CS/SS) pin is HIGH. For example, LE being HIGH for 1-2 CLK cycles will switch the 16 outputs as per the buffered bits, whereas LE being HIGH for 3-4 CLK cycles will load the 16 bits to a brightness register.

Digital Keys

Question

How can I toggle my LE/CS/SS pin for a specific number of SCLK cycles? I had intended to use the SPI Libary, however I'm not sure this can be supported.

Many Thanks!

Short answer: you can't :frowning:

Possible hardware solutions that come into mind:

  • Add a shift register that you fill with the key pattern and shift it out to the LE pin while outputting the data by SPI.
  • Add a presettable counter which you set to the desired number of pulses, connect its "32" (5th bit) output to LE and count up (or down) during the SPI transfer.
    An internal timer/counter may serve that purpose as well?

Or find some easier controllable LED driver chip...

1 Like

Hi there, thank you for your input, despite confirming my fears!

On the hardware approach, could I not simply use a 1:2 DEMUX to switch my MOSI to the LE line? A chip such as NL7SZ19?

MOSI transfers 16 bit data while LE indicates their target register.

Yes, sorry, I wasn't clear.

What I'd thought to do was use a DEMUX to switch my Arduino MOSI line to the LE line of the IC, then SPI out the corresponding byte(s) for the required function. For example 0x7 or 0xF for the key "Data Latch", being 2-3 Clock Cycles. This might need to be 0x70 or 0xF0 depending on endianness.

Both informations must be output at the same time.

1 Like

Right! Okay, I've caught up. A critical misunderstanding. Thank you for your time :slight_smile:

Yes, you can.

That, you can't.

How fast do you need to transfer data? I would suggest coding it in software ("bit-banging"), using the standard digitalWrite(), >> bit-shifting etc. and get it working, even if it's not as fast as you would like. Then there are some tricks to get an extra turn off speed we can try. But don't go as far as direct port manipulation, because that ties you to the model of MCU, and you may ultimately need to upgrade to a faster MCU to get the speed you need.

Hello and thanks for joining.

For my application I'll be looking to write out 16 bits, to each of the 16 outputs, on my 13 drivers, at minimum 100Hz so... like 42kBps by my reckoning? As I understand that's well under the 8MHz SPI minimum of most Ardunios?

To be honest I've always assumed that you couldn't be sure on the accuracy of your timings with standard digitalWrite()s etc. Any examples or reference you might recommend?

There's no minimum clock frequency ...

So maybe shiftOut() is an alternative (see reply#8).

Following the advise received here, I've created a modified shiftOut() of ArduinoCore-avr/cores/arduino/wiring_shift.c to be as:

void keyedShiftOut(
  uint8_t dataPin,
  uint8_t clockPin,
  uint8_t latchPin,
  uint8_t bitOrder,
  uint16_t val,
  uint16_t key)
{
	uint8_t i;

	for (i = 0; i < 16; i++)  {
		if (bitOrder == LSBFIRST) {
			digitalWrite(dataPin, val & 1);
			val >>= 1;
            digitalWrite(latchPin, key & 1);
			key >>= 1;
		} else {	
			digitalWrite(dataPin, (val & 0x8000) != 0);
			val <<= 1;
            digitalWrite(latchPin, (key & 0x8000) != 0);
			val <<= 1;
		}
			
		digitalWrite(clockPin, HIGH);
		digitalWrite(clockPin, LOW);		
	}
}

I used this to implement the sequence described within the data sheet (Figure 24. Brightness register setting) to set all of my 16 Brightness Registers to a half setting (0x7FFF) with a timed LE providing the digital key. This scoped out as:

Running on my Arduino Nano 33 IoT this clocked at 150kHz which is more than sufficient for my application.

Many Thanks

CODE EDIT: As per @DrDiettrich comment below.

Shouldn't this (and next) read as
digitalWrite(dataPin, (val & 0x8000) != 0);

1 Like

Yes, absolutely, thank you.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.