cancel
Showing results for 
Search instead for 
Did you mean: 

Question on SPI communication

Tbone1
Associate II

Hi 

I am learning to write driver code for SPI. I have an nucleo-L476RG development board with me implementing full-duplex transmit only operation and reading the output of a MOSI pin using a logic-analyzer. The Nucleo board is working as the master

So far this is my understanding of the SPI based on the reference manual.

  1. 2 x 32-bit FIFO buffers one for Rx and One for Tx
  2. The number of data that can be transmitted : 4 bits - 16 bits, it can be configured in the CR2-> DS register of the respective peripheral
  3. When the data < 8 bits the data is packed to 8 bits, when the  8< data < 16 bits the data is  packed to 16 bits

SPI Parameters

SPI Peripheral - SPI1

Clock Frequency - 4 MHz

Baud Rate - SYS_CLK_DIV_64

CPHA - First Clock Edge

CPOL - Zero when Idle

LSB First - Data transmitted with MSB first

Data Size - 8 bits per frame

Communication Mode - Full duplex(BIDIMODE:0, BIDIOE:0, RXONLY: 0)

Software Slave Management - Enabled

Internal Slave Select -1

Device Mode - Master

GPIO Pin Configuration

GPIO A, Pin 5 -SPI CLK

PinMode - Alternate Function

Alternate function Mode - AF5

Output Type - Push-Pull

GPIO Speed - Default - Not configured

GPIO A, Pin 6 - SPI_MISO

PinMode - Alternate Function

Alternate function Mode - AF5

Output Type - Push-Pull

GPIO Speed - Default - Not configured

GPIO A, Pin 7 - SPI_MOSI

PinMode - Alternate Function

Alternate function Mode - AF5

Output Type - Push-Pull

GPIO Speed - Default - Not configured

GPIO A, Pin 4 - SPI_NSS

PinMode - Alternate Function

Alternate function Mode - AF5

Output Type - Push-Pull

GPIO Speed - Default - Not configured

Output from logic analyzer:

Case: 1 Data transferred: 0x1

0693W00000JPooRQAT.pngCase :2 Data Transferred : 0x2F, Data Size(DS= 4)

0693W00000JPoobQAD.pngI have implemented the blocking call for SPI so far in my logic,

Questions:

  1. In Case-1 I have set the DS size to 8 bits and my data is also of uint8_t why then is 16 clocks sent from the master?
  2. In Case-2 when the DS is set to 4 bits why are the bits after 4 bits sent(binary of 0x2F is 0010 1111)?
  3. I have not configured the Pin speed of the pin in the GPIO configuration, is it necessary to configure it as the High speed?
  4. I have an another case which is not documented here, say I have an slave which will reply back with a value(16-bit) based the address represented by 4 bits of the MOSI, in this case how should the clock be configured to output 8+16 clocks to successfully transact the information
1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

1+2) Show the actual code. You may be sending more data than you think due to data packing.

3) You can see max frequency of pins vs speed setting in the datasheet. If it's working, it's probably fine.

4) Writing 3x 8-bit values to DR in 2-line mode will produce 24 clocks.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

8 REPLIES 8
Breakthecake
Associate II

Hi Tbone,

maybe we both take part in the same online course ... 😉

  • Why do you choose software slave management and configure the /NSS pin? - By the way, in case you prefer to use the /NSS pin, use an external pull-up resistor or configure the GPIO to use one. In my case (same µC etc.) that should be the reason why the slave is not selected. A friendly user told me, the /NSS pin is not properly documented in the ref man. It needs a pull-up resistor added!
  • What kind of slave do you have? I assume from what you wrote, you just read the CLK and MOSI pins, right?
  • Q no. 1 and 2: I experienced the same in my studies.
  • Q no. 3: As far as I heard the speed is not relevant on a relatively slow bus clock and short distancy master to slave.
  • Q no. 4: I did not understand what you meant. Perhaps you may ask a separate question for this topic.
  • You wrote the data size is 8 bit per frame. Have you checked what the register says after initialization/after finishing the data transfer?

TDK
Guru

1+2) Show the actual code. You may be sending more data than you think due to data packing.

3) You can see max frequency of pins vs speed setting in the datasheet. If it's working, it's probably fine.

4) Writing 3x 8-bit values to DR in 2-line mode will produce 24 clocks.

If you feel a post has answered your question, please click "Accept as Solution".
S.Ma
Principal

My quick checklist:

The number of sck clocks depends on data transmitted, even dummy one when need to read from slave.

A master sck clock is completed once the reception is complete, not transmit buffer empty which is to avoid pause between transmitted bytes. The fifo relaxes this further.

The fifo is sensitive to the core data bus, if you write 8 bit, 8 bit is queued, if you write 16 bit, 2x8 bit will be queued for the 8 bit spi.

Nss is important to sync the slave, it is equivalent to a start stop bit.

Beware, when implementing later a spi slave in the mcu with dma in cyclic mode, your transmit fifo will clog when nss goes up, and you may need to sw reset and reconfigure the spi....

Tbone1
Associate II

Hi TDK,

Thank you for your inputs, based on it I found that the controller was writing 16bit to the SPI1->DR register. Earlier I had implemented it as

//8 bit transfer ,pTxBuffer = pointer to uint8_t 
pSPIx->SPI_DR = *pTxBuffer; 

Now It works when after typecast now the code looks like

//8 bit transfer ,pTxBuffer = pointer to uint8_t 
*((uint8_t*)&pSPIx->SPI_DR) = *pTxBuffer;

Now the logic analyzer send out 8 bit when the data size is configured as 8 bits

@Community member​  If you are still figuring out why 16 clocks are sent out when the data size is set as 8 bit, this might be a possible solution

I can confirm that's the way to code it! Funny, the teacher of the online course coded like Tbone in his first quote and it seemed to work fine for the stm32Fxxx µC, but not for the L-type! Of course, this is not documented in the ref man.

Dear ST staff, please tell the users in your manuals about those important facts!

It absolutely is documented in the reference manual. Look up “data packing�?.
If you feel a post has answered your question, please click "Accept as Solution".

Well TDK,

I think there is a misunderstanding. I was commenting on

//8 bit transfer ,pTxBuffer = pointer to uint8_t 
    *((uint8_t*)&pSPIx->SPI_DR) = *pTxBuffer;

As mentioned, a teacher on a course using the stm32Fxx type did not have to code like this to get the sending done. Data packing was not the issue.

Have a good day. 😉

Right, because the STM32F4 family doesn’t have data packing, so casting like this is not needed. I'm not sure of the miscommunication. I was responding to this: 

> ... it seemed to work fine for the stm32Fxxx µC, but not for the L-type! Of course, this is not documented in the ref man.

Data packing is documented in the reference manual of the L4 and other families where it is a feature. It's not documented in the F4 and other families where it's not a feature. Perhaps you are saying something else, I'm not sure. No ill-will intended, cheers.

If you feel a post has answered your question, please click "Accept as Solution".