Skip to main content
luch
Associate II
April 24, 2020
Solved

STM32F746 SPI basic usage

  • April 24, 2020
  • 3 replies
  • 1400 views

Hi everybody!

I've been struggling with this monster for a few days now. I'm trying to make it do some very basic (pun not intended) things and I have little hair left... But let's cut a (too) long story short: I'd like to send with the SPI a few bytes to a device. I'm using polling (DMA and INT's is an epic drama for another time), although that's not relevant at this point. So let's just send a byte (8 bits) thru SPI. I've set up the GPIOs for the SPI normal, as alternate functions (most of this code has been generated by CubeMX) - with NSS port as normal output - like this:

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_SPI_InitTypeDef SPI_InitStruct = {0};
 
GPIO_InitStruct.Pin = CK_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
GPIO_InitStruct.Pin = MOSI_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
GPIO_InitStruct.Pin = MISO_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; 
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

And this is the interesting part, the SPI setup:

SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;			// this is like using Bytes, right?
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 7;
LL_SPI_SetRxFIFOThreshold(SPI4, LL_SPI_RX_FIFO_TH_QUARTER); //the infamous FIFO, ignored in most STM examples,
													 // just like the NSS output
LL_SPI_Init(SPI4, &SPI_InitStruct);
LL_SPI_SetStandard(SPI4, LL_SPI_PROTOCOL_MOTOROLA);
 
 // then I enable SPI:
 SET_BIT(SPI4->CR1, SPI_CR1_SPE);
 // so far, so good. And now I try to send a byte:
 
 SPI1->DR = data;	//data defined as a uint8_t of a whatever value

what I get is 8 bits of 'data' on MOSI and CLK outputs, followed by another 8 bits of CLK and MOSI=0. In total 16 bits/pulses. Why is that?! How can I convince this animal to give what is set up for - 8 bits? What do I miss?

Thank you in advance for any input!

This topic has been closed for replies.
Best answer by TDK

You're pushing 16 bits into the register. You need to access it as a byte, rather than a word.

Use LL_SPI_TransmitData8, or duplicate its functionality:

/**
 * @brief Write 8-Bits in the data register
 * @rmtoll DR DR LL_SPI_TransmitData8
 * @param SPIx SPI Instance
 * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF
 * @retval None
 */
__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData)
{
#if defined (__GNUC__)
 __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR);
 *spidr = TxData;
#else
 *((__IO uint8_t *)&SPIx->DR) = TxData;
#endif /* __GNUC__ */
}

3 replies

TDK
TDKBest answer
April 24, 2020

You're pushing 16 bits into the register. You need to access it as a byte, rather than a word.

Use LL_SPI_TransmitData8, or duplicate its functionality:

/**
 * @brief Write 8-Bits in the data register
 * @rmtoll DR DR LL_SPI_TransmitData8
 * @param SPIx SPI Instance
 * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF
 * @retval None
 */
__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData)
{
#if defined (__GNUC__)
 __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR);
 *spidr = TxData;
#else
 *((__IO uint8_t *)&SPIx->DR) = TxData;
#endif /* __GNUC__ */
}

"If you feel a post has answered your question, please click ""Accept as Solution""."
luch
luchAuthor
Associate II
April 25, 2020

Thank you, TDK! I will try this... I thought if I set SPI for 8 bits data processing, this what it will do. I would have rather expected that even if I intentionally put a 16 bit word into the DR, to have only 8 bits shifted out. I've also tried SPI1->DR=(uint8)data, although data was already defined as 8 bits. It was the wrong place for that hint.

But I've got your point and thanks again for that.

luch
luchAuthor
Associate II
April 25, 2020

Yes, it works! Many thanks TDK :thumbs_up: