cancel
Showing results for 
Search instead for 
Did you mean: 

Internal Working of SPI?

Sandeep Dhokne
Associate II
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.

16 REPLIES 16
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
Up vote any posts that you find helpful, it shows what's working..
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
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 II
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 II
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 II
Posted on July 27, 2017 at 11:53

0690X00000603pvQAA.jpg
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 ?

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.

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