LPC1788 - SPI performs unexpectedly

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1788 - SPI performs unexpectedly

1,953 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TKoe on Thu Nov 22 03:32:28 MST 2012
Hello!

I have configured an LPC1788 as SPI master on SSP0 (CPOL = 1; CPHA = 0) to communicate with a DAC chip at 30 MHz.
This chip needs the chip select pulled down (I do that with a GPIO), then three bytes of command data need to be transmitted and then the chip select needs to be pulled up again.

So to send any data I use the SSP_ReadWrite function and the data does get transmitted and the DAC updates its outputs accordingly. So everything's fine... except for one thing:

The three bytes that I transmit with this function aren't sent directly after another (as I would have expected) but between each byte there's a pause of about one or two microseconds. Below is the code that will transmit one of those three-byte-packages.
Also between two packages there's a pause of over TEN microseconds.
My question is: Why are there so long pauses and how would I go to reduce/remove them? Any hints are greatly appreciated!


Regards!

<code>
void setdac(t_dac_channel ch, uint16_t value)
{
uint8_t tx_data[3] = {0,0,0};
uint8_t rx_data[6];
tx_data[0] =
(0 << 7) |
(0 << 6) |
(0 << 5) |
(1 << 4) |
(0 << 3) |
((ch >> 2) & 1) |
((ch >> 1) & 1) |
((ch >> 0) & 1) ;
tx_data[1] = (value >> 8) & 0xFF;
tx_data[2] = (value >> 0) & 0xFF;

SSP_DATA_SETUP_Type ssp_data =
{
.tx_data = tx_data,
.tx_cnt = 3,
.rx_data = rx_data,
.rx_cnt = 3,
.length = 3,
.status = 0,
};
SPI_GPIO_PORT->MASK = ~(1 << SPI_SSEL_PIN);
GPIO_ClearValue(SPI_PORT, 1 << SPI_SSEL_PIN);  // pull down
SSP_ReadWrite(SPI_CH, &ssp_data, SSP_TRANSFER_POLLING);
while (!(SPI_CH->SR & 0x01)); // 0x01 == TFE (Transmit FIFO Empty)
GPIO_SetValue(SPI_PORT, 1 << SPI_SSEL_PIN);  // pull up
}
</code>
Labels (1)
0 Kudos
7 Replies

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TKoe on Thu Nov 29 01:44:07 MST 2012
Hi!

Thank you, that really helped. Now the time between two bytes is about 250 ns.
I replaced the library call with three lines actual code - didn't actually expect it to slim down that much for my application.

Best Regards!


<code>
void setdac(t_dac_channel ch, uint16_t value)
{
    // ...

    LPC_GPIO0->MASK = ~(1 << SPI_SSEL_PIN);
    GPIO_ClearValue(SPI_PORT, 1 << SPI_SSEL_PIN);

    while (cnt < 3)
    {
        if (SPI_CH->SR & SSP_SR_TNF) // (Transmitter Not Full)
        {
            SPI_CH->DR = tx_data[cnt++] & 0xFFFF;
        }
    }

    while (!(SPI_CH->SR & 0x01)); // 0x01 == TFE (Transmit FIFO Empty)
    GPIO_SetValue(SPI_PORT, 1 << SPI_SSEL_PIN);
}
</code>
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lien.Nguyen on Mon Nov 26 21:21:54 MST 2012
Hi,
Sorry about misleading you. I checked and thought that the SPI bit clock is the problem. If you would like to set it as 30Mhz, you must optimize the code of sending & receiving as fast as possible (the system clock is just 120Mhz). You have fixed the data wordwidth and the number of byte sent, so I think you should write hard code to send three bytes one after one. Don't use SSP_ReadWrite function in this case. :).

Best Regards,
Lien
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TKoe on Mon Nov 26 01:06:50 MST 2012
Well here's a shot from my scope.

Channel 1 is the DAC's output.
Channel 3 is a signal that's used for synchronization of the DAC's output. Must be pulled high while transmitting new values.
Channel 2 is the SPI's <del>MOSI</del> SCK.

You can see me sending the values to the DAC. The three bytes are quite far apart from each other.



Edit: Fixed one of the signals, oops!
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TKoe on Fri Nov 23 01:32:23 MST 2012
Hello!

That has exactly the same behaviour.
I wanted to make another shot from the scope, but found it to be pretty useless as the signals look the same, except that the SCK's idle state is LOW.


Best regards!
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lien.Nguyen on Thu Nov 22 20:38:13 MST 2012
Could you try setting CPOL=0,CPHA=1?
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TKoe on Thu Nov 22 04:28:17 MST 2012
Hi!

I must admit, I am not sure how to do this. Also this is the first time I'm using a SPI on an ARM processor. The user manual states that SSEL is an output pin when in master mode, furthermore it is automatically configured through pinsel, yet I am supposed to pulse that high?

Regards!
0 Kudos

1,770 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Lien.Nguyen on Thu Nov 22 04:01:19 MST 2012
As I know, if CPHA=0, you must pull SSEL between each data word transfer. This is said in User manual (section 21.5.2.4 SPI format with CPOL = 1,CPHA = 0).

Best Regards,
Lien
0 Kudos