jenswilly.dk


SPI on LPC1347 vs capacitance

Or "Capacitance matters – who'd've thunk it"

I am using SPI to talk to a MAX7456 video overlay IC from an LPC1347 MCU in my ROV project.

That should be easy enough since the LPC1347 contains twp SPI compatible synchronous serial ports ("SSP" for short). Perusing the manual and some code examples I came up with code to initialize the SSP for SPI comms and to send SPI data.

But, alas, it didn't work :(

Connecting my trusty Saleae Logic analyzer I saw that the CS line was toggled low and then high again for every byte. Which the MAX7456 apparently doesn't like – it wants the CS line to be low for the entire command (which consists of several bytes) – just as described in the datasheet.

So I switched to manually toggling a GPIO line low before transmitting SPI data and then high again when transmission is done. Like this:

#define MAX7456_CS_ON LPC_GPIO->CLR[ 1 ] = (1<< 13)
#define MAX7456_CS_OFF LPC_GPIO->SET[ 1 ] = (1<< 13)

MAX7456_CS_ON;

spi_transfer(VM0_reg);
spi_transfer(MAX7456_reset);

MAX7456_CS_OFF;

And, for reference, the spi_transfer() function looks like this:

void spi_transfer( uint8_t data )
{
    // Wait until SSP is not busy and TX FIFO is not full
    while ( (LPC_SSP0->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF )
        ;

    // Send data
    LPC_SSP0->DR = data;
}

But that didn't work either. Looking at the logic analyzer it turned out that CS came low several microseconds after the SPI transmission started. Weird, since the the GPIO pin is set low before I start the SPI. I also tried using the byte pin and word pin registers but the result was the same.

So it just looks like the GPIO is just really, really slow. What I finally came up with that works was this:

#define MAX7456_CS_ON { uint8_t i; LPC_GPIO->CLR[ 1 ] = (1<< 13); for( i=0; i<48; i++ ) __NOP(); }
#define MAX7456_CS_OFF LPC_GPIO->SET[ 1 ] = (1<< 13)

In other words: let the CPU wait for 48 clock cycles after setting the pin low before trying to do something else.

On the logic analyzer, it looks like this:

Logic analyzer capture. With delay.

Logic analyzer capture. With delay.

Still weird though. Until I connected a scope instead of a logic analyzer. Then it looked like this without the delay:

Scope capture. Without delay.

Scope capture. Without delay.

And this with the delay:

Scope capture. With delay.

Scope capture. With delay.

So it looks like the delay is, in fact, not the MCU's GPIO that is slow but rather capacitance. So even though the pin was toggled low the capacitance caused the voltage to decay slowly (relatively speaking) instead of instantly. So without the delay, the voltage never dropped low enough for the MAX7456 to consider the CS low. Now bear in mind that the pin is connected to the MAX7456 though the LPCXpresso board, the LPCXpresso Base Board, a jumper wire and then the MAX7456 breakout board. All of which have non-zero capacitance.

In other words: when working with high-speed (in this case 4 MHz) signals, make sure you design the board with that in mind and minimize capacitance (and inductance).

Unfortunately, I have no experience with that kind of semi-advanced PCB layout. Fortunately I can fix it in software and the delay I introduce will not pose a problem in this case.


2 comments on "SPI on LPC1347 vs capacitance"

[...] (This is a follow-up to my last post about GPIO delay and capacitance.) [...]

a_unique_identifier says:

Hello Jens,

a nice bit of information on this subject. Thanks! I'm just starting my SPI code adventure now - would you be willing to share your routines with me?

Also, thanks also for the interesting software based UART article. That was also something I wanted to try in the future. Did NXP simply not test their code? I find that hard to believe!

Cheer,
Joseph

Leave a Reply