cancel
Showing results for 
Search instead for 
Did you mean: 

SPI NSS interrupt

redmonds2
Associate II
Posted on August 25, 2010 at 13:48

SPI NSS interrupt

5 REPLIES 5
Posted on May 17, 2011 at 14:04

>>Option 3. Use the Receive interrupt (which might perhaps occur at the same time as the end of transmission). This seems dreadfully contrived, when all I want to do is transmit not receive.

This would seem the most viable, the TX interrupt is designed to permit SPI data to be streamed, as soon as the data is committed to the shift register you have some latency to allow for the loading of additional data into the output buffer. The RX is apt to occur once all the data has been shifted in, for the same reason. Many SPI applications anticipate data coming in as data goes out, to the point where you often have to send ''junk'' out to get the desired clocks to receive data coming back. Who cares if you just want to transmit, just ignore the incoming data if it is not important and use the interrupt for your own desired purpose. It is not as if receiving phantom data is going to cost any more in time/power/resources.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
redmonds2
Associate II
Posted on May 17, 2011 at 14:04

I suppose that SPI transmits of more than one byte/word that use DMA could interrupt on DMA Complete. But setting up a DMA to transmit one byte seems a bit clunky.

redmonds2
Associate II
Posted on May 17, 2011 at 14:04

Thanks Clive,

I think I agree with you. But if that was how ST designers had intended developers to generate an interrupt to deactive Chip Select after the transmission, it would be nice if they had provided that suggestion in the data sheet. It wasn't obvious to me (maybe there's an app note about it somewhere).

Or they could just have implemented NSS...etc.

At least now anyone else reading this won't have to rack their brains and waste the time that I have (assuming it works - I'll post a follow-up when I've tried it).

Thanks again,

Richard

Posted on May 17, 2011 at 14:04

Yes, using DMA does seem like overkill, when all you need is the interrupt. Plus it is likely to generate the interrupt as the last byte is commited to the SPI buffer, not when the last bit shifts out, unless you interrupt on a second byte. So abstracting through the DMA controller probably won't help.

I suspect the TC state is more important for the USART seeing as it is an ''asynchronous'' interface, and SPI is a ''synchronous'' one, and TX/RX are tightly bound together. Most of the decisions I think are driven by the high-speed flash models, and many real SPI peripherals are hardware state machines. The ''soft'' one probably have received less thought, but the peripherals on the STM32 are usually sufficiently flexible to achieve most goals.

I haven't physcially tried the SPI RX interrupt in this fashion, by the circuit is synchronous, and the interrupt latches as the shift register is migrated to the buffer. What the exact timing is I don't know, but you're going to have some latency servicing the interrupt. I would probably get the SS pin where you want, and then read the RX register to clear the pending interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
redmonds2
Associate II
Posted on May 17, 2011 at 14:04

>(assuming it works - I'll post a follow-up when I've tried it).

Yep, that nailed the sucker.

For anyone else going down this road...

void Spi1Init(void)

{

    ...

    /* config ''SPI Transmit Complete'' (i.e.RXNE) interrupt */

    NVIC_EnableIRQ(SPI1_IRQn);

    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);   

    ...

}

void Spi1TxData(uint16_t data)

{

    /* Wait for SPI1 Tx buffer empty */

    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

    nss_low();

    SPI_I2S_SendData(SPI1, data);

}

void SPI1_IRQHandler(void)

{

    volatile uint16_t spi_sr = SPI1->SR;

    if (spi_sr & SPI_I2S_FLAG_RXNE)

    {

        uint16_t dummy = SPI_I2S_ReceiveData(SPI1);    //dummy read to clear interrupt

        nss_high();

    }

}