cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F051C8 / SPI / half duplex / single line / Problem changing SPI_BiDirectionalLineConfig()

AlexandreR
Associate II

Hello everybody,

On actual project, I need to interface my STM32F051C8 to a HTS221TR Temperature & Humidity sensor.

Communication is through SPI1, STM32 is master, there is 1 bidirectional data line, 1 clock, 1 Slave Select.

Final usage will be in polling mode, actual tests are with delays only.

For first HW trials. polling and Slave Select are NOT implemented, since I go step by step to fid out errors.

To read data I need to:

·        Set data line to Tx

·        put SS low (will be done in later stage)

·        Send 0x8F (8 bits ), resulting in 8 clock + 8 datas (OK on oscilloscope)

·        (!!!) Set data line to Rx

·        Send dummy data's (8 bits ), resulting in sedning 8 clock + 8 datas read from bus

·        put SS high (will be done in later stage)

·        read Rx Buffer

The first 8 bits send out works perfectly.

Problem is, at the moment I set bidirectional line to Rx (line with !!! at the beginning), it immediately starts clocking SPI, for unlimited cycles. Even if I put breakpoint just after this instruction. But it should only start once sending dummy data's, and also only for 8 clocks.

What is wrong in my thinking ?

Below code is without polling (just put some delays), and without SS management (to avoid SS line getting high in between first 8 clocks and second 8 clocks, SS will be set to SW later)

I'm thankfull for any Idea !

Alexandre

void SPI1_Init(void)

{

   GPIO_InitTypeDef GPIO_InitStructure = {0};

   SPI_InitTypeDef SPI_InitStruct = {0};

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);   // SPI clock

   T_RCC_GPIO_ClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  // GPIO clock

   T_RCC_GPIO_ClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);  // GPIO clock

   //SPI1 GPIO Configuration

   //PA4  ------> SPI1_NSS

   //PA5  ------> SPI1_SCK

   //PB5  ------> SPI1_MOSI

 /* Connect PA4 to SPI NSS */

 GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_0);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

// GPIO_InitStructure.Alternate = GPIO_AF_0;

 GPIO_Init(GPIOA, &GPIO_InitStructure);

 /* Connect PA5 to SPI SCK */

 GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

// GPIO_InitStructure.Alternate = GPIO_AF_0;

 GPIO_Init(GPIOA, &GPIO_InitStructure);

 /* Connect PB5 to SPI MOSI */

 GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

// GPIO_InitStructure.Alternate = GPIO_AF_0;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

 /* Initialize the SPI_Direction member */

 SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; 

 /* Initialize the SPI_Mode member */

 SPI_InitStruct.SPI_Mode = SPI_Mode_Master; 

 /* Initialize the SPI_DataSize member */

 SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; 

 /* Initialize the SPI_CPOL member */

 SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;

 /* Initialize the SPI_CPHA member */

 SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;

 /* Initialize the SPI_NSS member */

 SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;

 /* Initialize the SPI_BaudRatePrescaler member */

 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

 /* Initialize the SPI_FirstBit member */

 SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;

 /* Initialize the SPI_CRCPolynomial member */

 SPI_InitStruct.SPI_CRCPolynomial = 7;

 SPI_Init(SPI1, &SPI_InitStruct);

}

void SPI1_Read_Data()

{

   SPI_InitTypeDef SPI_InitStruct = {0};

uint8_t Received_DATA_from_SPI;

   SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);

 SPI_Cmd(SPI1, ENABLE);

   SPI_SendData8(SPI1, 0x8F); //b 1(read) 0(no increment) 001111 (WHO AM I)

   TM_Delay(1);

  SPI_Cmd(SPI1, DISABLE);

SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Rx);

  SPI_Cmd(SPI1, ENABLE);

   SPI_SendData8(SPI1, 0xFF);

   TM_Delay(1);

   Received_DATA_from_SPI = SPI_ReceiveData8(SPI1);

  SPI_Cmd(SPI1, DISABLE);

}

10 REPLIES 10
Dzor
Associate III

Your example helped me to figured it out. (In my case with TLE5012.)

Your code works if you don't disable SPI just before enabling RX mode (and thus the clock). And also dummy Read in TX mode seems to be necessary for some reason. Alternatively, if I change direction at the end of the function, instead of the beginning, then it works without dummy Read.

Also, for some reason I have clear receive buffer, after

void SPI1_Read_Data()
{
   SPI_InitTypeDef SPI_InitStruct = {0};
   uint8_t Received_DATA_from_SPI;
  
   SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Tx);
   SPI_Cmd(SPI1, ENABLE);
   SPI_SendData8(SPI1, 0x8F);
   SPI_ReceiveData8(SPI1); //dummy read
   
   TM_Delay(1);
 
   SPI_BiDirectionalLineConfig(SPI1, SPI_Direction_Rx);
   TM_Delay(1);
   Received_DATA_from_SPI = SPI_ReceiveData8(SPI1);
   SPI_Cmd(SPI1, DISABLE);
 
}