cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F091RCT6 SPI Peripheral weird behavior with 8 bits data mode

Frederic REMY
Associate II
Posted on June 09, 2017 at 11:23

Hello,

I have a

weird

  behavior with STM32F091RCT6 SPI Peripheral on Nucleo Evaluation Board.

I want to interface with a 25LC640 SPI eeprom with 8 bits data mode

When i want to send a byte, i see On Oscilloscope 16 clocks pulse instead of 8 !!

I have tested several setting, i have the good number of pulses for 9 bits data size and more .

Context :

STM32F091RCT6

HAL library 1.6

Keil IDE & compiler : 5.06

SPI2 Peripheral on Port B Pin 13,14,15 Master Mode without NSS pin

SPI setup like this :

void MX_SPI2_Init(void)

{

  hspi2.Instance = SPI2;

  hspi2.Init.Mode = SPI_MODE_MASTER;

  hspi2.Init.Direction = SPI_DIRECTION_2LINES;

  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;

  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi2.Init.NSS = SPI_NSS_SOFT;

  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;

  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi2.Init.CRCPolynomial = 8;

  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  if (HAL_SPI_Init(&hspi2) != HAL_OK)

  {

    Error_Handler();

  }

}

    __HAL_RCC_SPI2_CLK_ENABLE();

       __HAL_SPI_ENABLE(spiHandle);        

 

    /**SPI2 GPIO Configuration    

    PB13     ------> SPI2_SCK

    PB14     ------> SPI2_MISO

    PB15     ------> SPI2_MOSI

    */

    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

Sending function :

static uint8_t eep_SpiSendByte (uint8_t data)

{

    while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);             // Wait for empty transmit buffer

    EE_SPI->DR = data;                                                                      

    while (( EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);           // Wait for received buffer with new data

    return (uint8_t)EE_SPI->DR;

}

Thanks

#stm32f091-spi-spi_datasize_8bit #hal-v1.6
14 REPLIES 14
Posted on June 14, 2017 at 16:08

Edit: why is this being moderated ? Syntax highlighter ?

I strongly suspect they check every code snippet with <LARGE DATABASES> for copyright protection violations before rolling it out.

And there seems to be a list of code words that trigger a detour through moderation.

Posted on June 14, 2017 at 17:18

Yes that would make sense...

Frederic REMY
Associate II
Posted on June 16, 2017 at 10:37

I test the solution given by waclawek.jan and i understood it with Kraal explanation.

Thanks a lot !!

Now i could seed 4 separated bytes on scope. But it work if I put a little delay after the last wrote of the data register to received the the reading byte !

I have tested three solutions , and I think there is a strange behavior of Rx Fifo in STM32F091.  Only one with the delay works.

Normal Case Doesn't work all reading value are 0 :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    return (uint8_t)EE_SPI->DR;

}

Corrected previously case with delay :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    delayUS(10);

    return (uint8_t)EE_SPI->DR; }

Tested Reception with Rx Fifo Level in FRLVL[1:0] in Status Register like this :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF;         // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    while ((EE_SPI->SR & 0x0600) != 0x0000)

    while ((EE_SPI->SR & 0x0600) != 0x0200)

    return (uint8_t)EE_SPI->DR;

This last method work for the first eeprom reading byte, after we have always the same value.

Whe also tested empty Transmit buffer before transmit with this method :

static uint8_t eep_SpiReceiveByte (void)

{

    while ((EE_SPI->SR & 0x1800) != 0x0000)

    while ((EE_SPI->SR & SPI_SR_TXE_Msk) == RESET); // Attente du buffer de transmission vide

    *(volatile uint8_t*)&EE_SPI->DR = 0xFF; // 8 cycles d'horloge

    while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

    return (uint8_t)EE_SPI->DR;

Nothing better !

It appears that RXNE is not a good information to now if a valid byte is in the receveid buffer.

How does the Rx Fifo work ?

Posted on June 16, 2017 at 11:47

while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET)

You want to put a semicolon ; or an empty compound statement {} after this statement.

JW

Posted on June 16, 2017 at 14:26

It's work now ................

Oupsss

>:(

Thanks