cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F746 SPI basic usage

luch
Associate III

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!

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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".

View solution in original post

3 REPLIES 3
TDK
Guru

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
Associate III

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
Associate III

Yes, it works! Many thanks TDK 👍