Skip to main content
Sandeep Dhokne
Associate III
July 26, 2017
Question

Internal Working of SPI?

  • July 26, 2017
  • 16 replies
  • 2435 views
Posted on July 26, 2017 at 12:15

Hi,

When i checked on DSO  (scope)  i found that after chip select SPI_NSS latch to ground.

there in clock signals on clk pin.

there is no data on SI and SO pin.

Why there no data on SPI's Pin?

Why SPI_NSS latch to ground? 

Anybody please help.

What is the internal working of HAL SPI protocol?

Initialization of SPI

void MX_SPI1_Init(void)

{

hspi1.Instance = SPI1;

hspi1.Init.Mode = SPI_MODE_MASTER;

hspi1.Init.Direction = SPI_DIRECTION_2LINES;

hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;

hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi1.Init.TIMode = SPI_TIMODE_DISABLED;

hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

hspi1.Init.CRCPolynomial = 10;

HAL_SPI_Init(&hspi1);

}

My Code:

void InitMemory(void)

{

PageAdd = 0; 

ByteAdd = 0;

ByteCount = 1;

ReadMemory(&TotalReportNo, PageAdd, ByteAdd, ByteCount);

ReportNo = TotalReportNo + 1;

}

void ReadMemory(UCHAR *bData, UINT PageId, UINT ByteId, UINT NoOfBytes)

{

int Status;

Status = 1;

//--------------------------------------------------------------------------------------------------------------------------------------------------------------

while(Status != HAL_OK)

{

Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(0xd2),(uint8_t*)(&aRxBuffer),1,1000);

}

while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

//

--------------------------------------------------------------------------------------------------------------------------------------------------------------

while(Status != HAL_OK)

{

Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)((UCHAR)((PageId>>7) & 0xFF)),(uint8_t*)(&aRxBuffer),1,1000);

}

while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

//

--------------------------------------------------------------------------------------------------------------------------------------------------------------

while(Status != HAL_OK)

{

Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)((UCHAR)((PageId<<1)|(ByteId>>8)) & 0xFF),(uint8_t*)(&aRxBuffer),1,1000);

}

while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

//

--------------------------------------------------------------------------------------------------------------------------------------------------------------

while(Status != HAL_OK)

{

Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)((UCHAR)(ByteId & 0xFF)),(uint8_t*)(&aRxBuffer),1,1000);

}

while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

//

--------------------------------------------------------------------------------------------------------------------------------------------------------------

while(Status != HAL_OK)

{

Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(0x00),(uint8_t*)(&bData),NoOfBytes,1000);

}

while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

//

--------------------------------------------------------------------------------------------------------------------------------------------------------------

}

Thank you.

    This topic has been closed for replies.

    16 replies

    Tesla DeLorean
    Guru
    July 26, 2017
    Posted on July 26, 2017 at 12:53

    The byte pointers can't be cast like that. Put the data into a byte/char variable and create a pointer to that.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Vangelis Fortounas
    Associate II
    July 26, 2017
    Posted on July 26, 2017 at 12:56

    Hello Sandeep!

    First of all, I your port fully initialised? (spi clock enable, GPIO redirected)?

    at your first calling funtion to transmit  '(uint8_t*)(0xd2)' you mean that 0xd2 is a pointer to data buffer. . Is not correct.

    also (uint8_t*)((UCHAR)((PageId>>7) & 0xFF)) is not a pointer to something

    also the (uint8_t*)((UCHAR)((PageId<<1)|(ByteId>>8)) & 0xFF) is not a pointer to something

    etc..

    Make it simpler  by call

    uint8_t bt;

    HAL_SPI_Transmit(&hspi1, &bt, 1, 1000);

    to observe the behaviour  and to eliminate any hardware initialisation error.

    Tilen MAJERLE
    ST Employee
    July 26, 2017
    Posted on July 26, 2017 at 16:05

    Hello

    As mentioned by

    , you have to save your desired byte to variable first and then pass pointer to function to send.

    uint8_t data = 0xd2;HAL_SPI_TransmitReceive(&hspi1, &data, aRxBuffer, 1, 1000);�?�?�?�?

    Best regards,

    Tilen

    Sandeep Dhokne
    Associate III
    July 30, 2017
    Posted on July 30, 2017 at 07:41

    Hi,

    The problem I'm having right now is that the NSS pin is always low. Clock and MOSI are perfect. What I would like is that the NSS is high, and goes low during the transmission, then high again.

    Sandeep Dhokne
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 09:33

    Thank you.

    I did the changes according to your valuable suggestions.

    But till i didn't received any clock pulses on SPI Clock pin.

    SPI NSS (Chip Select)  ground to latch as soon as it enters in SPI write funcion.

    I want to interface STM32F405 and Flash memory IC ATMEL AT45DB041.

    pls check

    my initialization of SPI :

    void MX_SPI1_Init(void)

    {

    hspi1.Instance = SPI1;

    hspi1.Init.Mode = SPI_MODE_MASTER;

    hspi1.Init.Direction = SPI_DIRECTION_2LINES;

    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

    hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;

    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hspi1.Init.TIMode = SPI_TIMODE_DISABLED;

    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    hspi1.Init.CRCPolynomial = 10;

    HAL_SPI_Init(&hspi1);

    }

    __SPI1_CLK_ENABLE();

    /**SPI1 GPIO Configuration

    PA4 ------> SPI1_NSS

    PA5 ------> SPI1_SCK

    PB4 ------> SPI1_MISO

    PB5 ------> SPI1_MOSI

    */

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;//GPIO_MODE_AF_PP

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;//GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    My New Code:

    void WriteMemory(UCHAR *bData, UINT PageId, UINT ByteId, UINT NoOfBytes)

    {

    int Status,Count;

    Status = 1;

    SPI_TX = 0;

    SPI_RX = 0;

    SPI_TX = 0x82;

    while(Status != HAL_OK)

    {

    Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(&SPI_TX),(uint8_t*)(&SPI_RX),1,1000);

    }

    while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

    SPI_TX = ((UCHAR)((PageId>>7) & 0xFF));

    while(Status != HAL_OK)

    {

    Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(&SPI_TX),(uint8_t*)(&SPI_RX),1,1000);

    }

    while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

    SPI_TX = ((UCHAR)((PageId<<1)|(ByteId>>8)) & 0xFF);

    while(Status != HAL_OK)

    {

    Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(&SPI_TX),(uint8_t*)(&SPI_RX),1,1000);

    }

    while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

    SPI_TX = ((UCHAR)(ByteId & 0xFF));

    while(Status != HAL_OK)

    {

    Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(&SPI_TX),(uint8_t*)(&SPI_RX),1,1000);

    }

    while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

    for(Count=0 ; Count<NoOfBytes ; Count++)

    {

    SPI_RX = 0x00;

    while(Status != HAL_OK)

    {

    Status = HAL_SPI_TransmitReceive(&hspi1,(uint8_t*)(&bData),(uint8_t*)(&SPI_RX),NoOfBytes,1000);

    }

    while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

    }

    }

    please help.

    Thank you.

    Sandeep Dhokne
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 11:47

    At power on status of all pins (SI,SO,SCLK,NSS) are high.

    When routine enters in SPI Write then NSS and SCLK latch to ground permanently .

    But there is a data on SI pin.

    Default Settings:-

    /**SPI1 GPIO Configuration

    PA4 ------> SPI1_NSS

    PA5 ------> SPI1_SCK

    PB4 ------> SPI1_MISO

    PB5 ------> SPI1_MOSI

    */

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    my initialization of SPI :

    void MX_SPI1_Init(void)

    {

    hspi1.Instance = SPI1;

    hspi1.Init.Mode = SPI_MODE_MASTER;

    hspi1.Init.Direction = SPI_DIRECTION_2LINES;

    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

    hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;

    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hspi1.Init.TIMode = SPI_TIMODE_DISABLED;

    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    hspi1.Init.CRCPolynomial = 10;

    HAL_SPI_Init(&hspi1);

    }

    Sandeep Dhokne
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 11:53

    0690X00000603pvQAA.jpg
    Vangelis Fortounas
    Associate II
    July 27, 2017
    Posted on July 27, 2017 at 12:52

    Sandeep hello again!.

    All this information you provide to us is fragmented.

    It is very dificult for us to help you to learn

    Need some info :  the board you use,  the MCU, clock configuration and pins you use to connect to memmory.

    Do you use CUBEMx? what is your IDE ?

    Sandeep Dhokne
    Associate III
    July 27, 2017
    Posted on July 27, 2017 at 13:16

    I am using

    Cubemx,

    IDE:Keil 5

    MCU:STM32F405 (using inbuilt SPI-1 engine).

    Flash Memory:Atmel AT45DB041

    MCU PIN's:

    /**SPI1 GPIO Configuration

    PA4 ------> SPI1_NSS

    PA5 ------> SPI1_SCK

    PB4 ------> SPI1_MISO

    PB5 ------> SPI1_MOSI

    */

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    //---------------------------------------------------------------------------------------------------------

    void MX_SPI1_Init(void)

    {

    hspi1.Instance = SPI1;

    hspi1.Init.Mode = SPI_MODE_MASTER;

    hspi1.Init.Direction = SPI_DIRECTION_2LINES;

    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

    hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;

    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hspi1.Init.TIMode = SPI_TIMODE_DISABLED;

    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    hspi1.Init.CRCPolynomial = 10;

    HAL_SPI_Init(&hspi1);

    }

    //-----------------------------------------------------------------------------------------------------

    void SystemClock_Config(void)

    {

    RCC_OscInitTypeDef RCC_OscInitStruct;

    RCC_ClkInitTypeDef RCC_ClkInitStruct;

    __PWR_CLK_ENABLE();

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;

    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

    RCC_OscInitStruct.PLL.PLLM = 2;

    RCC_OscInitStruct.PLL.PLLN = 3;

    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

    RCC_OscInitStruct.PLL.PLLQ = 5;

    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;

    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

    /* SysTick_IRQn interrupt configuration */

    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

    }

    Please refer above attached schematic. 

    Thank you.

    Vangelis Fortounas
    Associate II
    July 27, 2017
    Posted on July 27, 2017 at 14:26

    Hi Again!.

    Sandeep i dont understand how this initialisation code produced.

    RCC_OscInitStruct.PLL.PLLM = 2;

    RCC_OscInitStruct.PLL.PLLN = 3; // can 't be 3

    does not have any sense .

    Begin from Basics .

    Make a project at STM32CubeMX with your device (exact type)

    0690X00000603ymQAA.jpg

    put the value of your crystal in MHZ in the blue box and set clocks (eg like this)

    0690X00000603spQAA.jpg

    And initialize your spi port

    0690X00000603yrQAA.jpg

    Make some other settings to produce code for KEIL

    and generate the source projet

    fully initialized

    with theese setings

    then at your main function you can use

    Majerle.Tilen

    sugestion to transmit a byte!

    you must expect ~10MHZ pulse series from clock pin to measure with DSO