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
1 ACCEPTED SOLUTION

Accepted Solutions
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

View solution in original post

14 REPLIES 14
Posted on June 09, 2017 at 11:33

*(volatile uint8_t*)&EE_SPI->DR = data;   

AvaTar
Lead
Posted on June 09, 2017 at 11:45

Or perhaps this:

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

The TXE flag set does not mean the send finished, only the send data are moved to the hardware send reg.

I fell into this trap some time ago ...

Frederic REMY
Associate II
Posted on June 09, 2017 at 12:08

@ Avatar,

tanks for your suggestion, but i have yet the datasize problem on the fisrt byte !

When I send read instruction to 25LC640, it is the first byte after starting execution of program !

Posted on June 09, 2017 at 11:52

Perhaps, but it's more likely it's the 'data packing' feature, see RM0090  'data packing' subchapter of the SPI chapter.

A recurring issue here ever since the 'enhanced' SPIs appeared, first with 'F0.

JW

Posted on June 09, 2017 at 12:02

I think the above is the correct answer.

Frederic REMY
Associate II
Posted on June 14, 2017 at 12:42

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6sd&d=%2Fa%2F0X0000000bx9%2FJp_.W_1wbImvwjMGmQvsNnW_jzlcOwrc8svwRqrT4hc&asPdf=false
Frederic REMY
Associate II
Posted on June 14, 2017 at 14:24

@ Krall

Tanks for your reply :)

But i need to send one byte separately, and in 8 bits mode I have allways two bytes 16 pulses on Clock pin.

I can't use the data packing

Our driver work like this :

uint8_t eep_ReadByte (uint32_t adress)

{

    volatile uint8_t tmpRead;                                                /* For Trace

    EEP_CS_ENABLE;

    delayUS(5);

    eep_SpiSendByte(0x03);                                                /* Commande de lecture */

#if (defined EEP_25LC010) || (defined EEP_25LC020)

    eep_SpiSendByte((uint8_t)adress);                                /* Adresse à lire */

#elif defined EEP_25LC040

    #error 'code non ecrit'                                                      /* Autres instruction */

#elif defined EEP_25LC160 || (defined EEP_25LC320) || (defined EEP_25LC640) || (defined EEP_25LC256) || (defined EEP_25LC512)

    eep_SpiSendByte((uint8_t) adress >> 8);

    eep_SpiSendByte((uint8_t) adress);

#endif

    tmpRead = eep_SpiReceiveByte();

      TmpReadDebug = tmpRead ;                                         // for trace

    delayUS(5);

    EEP_CS_DISABLE;

    return tmpRead;

}

I have several other functions to managed a 25LCxxx witch are based on the following function :

Complementary eep_SpiSendByte and eep_SpiReceivedByte.

I didn't use HAL library because its too heavy and too slow in small STM32 for our product. (only for valid chip initialisation).

The 25LCxx Frame is divided in three part

instruction 8 bits

Adress 16 bits

Data 8 bits and more if need more data.

how i can now when one byte or two nibbles are receveid in RxFifo ?

while ((EE_SPI->SR & SPI_SR_RXNE_Msk) == RESET);        // Waiting Reception of Low Nibble

Or

while ((EE_SPI->SR & 0x0600) != 0x0400 )            // Waiting Two data In Fifo

Posted on June 14, 2017 at 13:40

But you don't have to use the 4 bit mode ! Have you tried the solution

Waclawek.Jan

gave you in the first reply ?

He even explained why you have this behavior, i.e. the data packing feature.

With his solution you want have to do all that stuff you do...

Posted on June 14, 2017 at 14:36

You didn't read carefully my answer, or didn't understand it completely.

Your function to send a byte is

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;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

And

told you that you should in fact write it like this

static uint8_t eep_SpiSendByte (uint8_t data){ while (( EE_SPI->SR & SPI_SR_TXE_Msk) == RESET);// Wait for empty transmit buffer *(volatile uint8_t*)&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;}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

The only difference is at line 4, it will force an 8-bit access to the data register of the SPI peripheral and it will send only 8 bits. No need to change to 4 bits mode at all. Try it and you will see by yourself.

Edit: why is this being moderated ? Syntax highlighter ?