SPI communication

Started by ksh 2 years ago10 replieslatest reply 2 years ago402 views


           I'm trying to use the SPI interface on a Laser Bee MCU to write/read data from an FRAM. I started with the SPI_Lib_Master example to learn how to use the SPI. Right now I'm trying to generate the bit sequences that I need in order to operate the memory. Using the SPI_Byte_Write function in the sample code (the function just places data into an array and sends it using SPI0_Transfer function in spi.c). I find that I need to send a dummy byte before transmitting data or my byte sequences is not correct. Right now, I have SPI_Byte_Write sending a single byte. If I want to send: 1001 1111 for example, I need to call SPI_Byte_Write twice, first to send 0000 0000 and then 1001 1111. If I do not send the dummy byte first the output on the MOSI line is 1000 0000. I can't figure out why this might be. Does it have to do with a way that the SPI is configured? Is there a way around this so that I can only send a single byte? Thanks!

[ - ]
Reply by mr_banditJune 13, 2018

SPI is really two shift registers: one on the master, one on the slave. When you put the first byte into the master's shift register (you "write to the master's data register") then you send (write) that data value, you end up swapping the values in the master and slave's data registers. So -the first byte from the slave is trash.

TO your specific question, what does the 0x9F mean? It should be a command, followed by an address and count (for a read) or an address (perhaps a count) and data bytes for write (speaking about communications with a generic FRAM).

The FRAM datasheet should give you the exact read/write sequence. I assume you are following this. It sounds like the FRAM is not ready to communicate over SPI, and the first byte "wakes it up". Does the same happen with the first byte being non-0x00? Does the datasheet say anything about waking the FRAM up or otherwise getting it ready for SPI? If your clock edge is not correct for the first bit, it can throw off a bunch of things.

What is the FRAM part number (so we can look at the datasheet)?

The other comments, below, are also spot-on. Setup is critical. Make sure the polarity of the SCK line is correct immediately after  init, and the bit sex (LS/MS first) is correct - for the FRAM - NOT the master.

[ - ]
Reply by KocsonyaJune 13, 2018
"So -the first byte from the slave is trash."

Not necessarily. Some slaves put a status byte into the data register at the falling edge of the slave select. That's what, for example, the CC1101 RF chip from TI does.

[ - ]
Reply by mr_banditJune 14, 2018

Interesting. Never seen that before. Thanks for the info!

[ - ]
Reply by SpiderKennyJune 13, 2018

I'd like to see the bit sequence on a scope to be sure. SPI is a funny thing, you send one byte, followed by 0 or more dummy bytes, and read the reply while you are still sending the dummy bytes. The dummy bytes are required for clocking the reply back in, as the master always provides the clock.

It is normal to have to send dummy bytes after a command byte, but I have never seen a situation where you need to send dummy bytes BEFORE the command byte.

Like I say, would be nice to check with a 'scope.

[ - ]
Reply by kshJune 13, 2018


 actually i wanted to clear it out that WHY is it necessary to send dummy bytes before transmitting actual data?

example: for WRITE command we send first frame that contains dummy bytes and second frame with actual msg/data

1st frame: cmd+msg_id+8 dummy_bytes+2 CRC

2nd frame: cmd+msg_id+8 bytes msg/data+2 CRC

[ - ]
Reply by matthewbarrJune 13, 2018

In general it should not be necessary to send an all 0's pad byte in front of a defined data transfer for a particular SPI slave device.  If it is necessary, the requirement should appear in the data sheet.  Whenever I find that to make something work I have to do something like this, I take it as a strong indication that something is wrong.

As someone already mentioned, there are different SPI modes of operation.  These define various aspects of SPI data transfer timing such as the state of clock when idle, the active clock edge, when the first data bit is transferred on MOSI/MISO, etc.  Your master device needs to be configured so that it is consistent with the slave device requirements.

I emphatically agree with the suggestion to look at the data transfer on the wire (SSEL, SPICLK, MOSI, MISO) and see what is actually being sent and received.  Hopefully there are example data transfers (timing diagrams) in the data sheet for your slave device to which you can compare your captured data transfer.

There are a lot of references on the web that describe timing for what is commonly referred to as Motorola SPI modes 0, 1, 2 and 3.  There are other SPI timing schemes, but most slave devices seem to use one of the Motorola modes.  This document from ARM contains timing diagrams for the four Motorola modes in sections 2.3.10 thru 2.3.13.

[ - ]
Reply by SpiderKennyJune 13, 2018

Also, the state of the CLOCK and MOSI lines prior to first transmission can dictate the phase and polarity of the signals - maybe you have an issue there?

[ - ]
Reply by sudheerg_June 13, 2018


At least while transmitting you shouldn't see this. 

As SpiderKenny stated for receiving data we need to send dummy bytes over MOSI line.

You may have to look at the initialization sequence in the MCU and match in the SPI example code.



[ - ]
Reply by arvindpdmnJune 13, 2018

No idea why but just a thought: have you configured SPI in the right mode, 0-3? To select the mode correctly, slave must be selected when the SCK is in the right level. Example:

[ - ]
Reply by RallygoerJune 13, 2018

Are you populating an array with the data, or are you using the SPI_Byte_Write function to do this? If you are populating the array before writing it out to the SPI bus are you certain the data in the array is correct. Also, if the array is being written to, by an SPI function, is it possible to populate your own array with the data you think you need, and parr that data into the SPIO_Transfer function. What FRAM part are you using? Are you using a scope to determine that the output on the MOSI line is 1000 0000?