cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f407 as SPI slave[HAL]

Evgeny Popov
Associate III
Posted on May 28, 2018 at 09:05

Im trying to catch data from the unknown device, this device has data and clock. I decided to make my stm32 as spi slave and catch the data as recevier.And im struggling with it. I have this data flow which i want to catch:

0690X00000602W8QAI.bmp

Clock is yellow and green is data.

I need only 16bytes from it, when data line goes low, we can see this 16bytes:

0690X00000602WDQAY.bmp

0690X00000602WIQAY.bmp

And there is the speed of the clock, as you can see its around 1.5us each clock pulse. So what i have to do is configure spi with HAL, i toolk SPI1(PA5 - CLOCK, PA7- DATA) cuz it has more powerful MHZ, chose spi mode ''RECEIVE ONLY SLAVE'', HARDWARE NSS SIGNAL: DISABLED. And here is my spi1 config:

static void MX_SPI1_Init(void)

{

/* SPI1 parameter configuration*/

hspi1.Instance = SPI1;

hspi1.Init.Mode = SPI_MODE_SLAVE;

hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;

hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi1.Init.NSS = SPI_NSS_SOFT;

hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;

hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

hspi1.Init.CRCPolynomial = 10;

if (HAL_SPI_Init(&hspi1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

What im doing in main.c, as oscilo's pictures says we need to catch the moment when data goes low and then try to read a data, im trying to catch first pulse then wait until data goes high then low and only they read spi, at least only first byte - it should be 0.

int main(void)

{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_DMA_Init();

MX_USB_DEVICE_Init();

MX_SPI1_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

uint8_t collect_bits = 0;

char string_array[21] = {0};

uint8_t spi_buffer[16] ={0} ;

spi_buffer[0] = 5;

// while (1)

// {

// HAL_Delay(10000);

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == 0){} // wait until GPIOC 9 goes high

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == 1){} // wait until GPIOC 9 goes high

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == 0){} // wait until GPIOC 9 goes high

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == 1){} // wait until GPIOC 9 goes high

HAL_SPI_Receive(&hspi1, (uint8_t*)spi_buffer, 16,0);

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

// }

/* USER CODE END 3 */

}

And i catch nothing at all, my spi buffer all 16 bytes are 0. I tried SPI_DMA it changed only first byte on 0XFF. What am i doing wrong? Thanks

#stm32f4-spi #receive

Note: this post was migrated and contained many threaded conversations, some content may be missing.
25 REPLIES 25
Posted on May 31, 2018 at 12:50

Please zip you code, its very difficult, when you don't have the code and a line number.

Posted on May 31, 2018 at 13:06

Hope direct drobox url is ok.

http://dl.dropbox.com/s/gdcq5dpyx31bxwc/SPI%20REGISTERS.zip?dl=0&file_subpath=%2FSPI+REGISTERS

Posted on May 31, 2018 at 14:04

we need to see the scope of the whole transaction,

where is the nSS trace ?

EDIT: this is not correct for the SPI slave function:

////////      but you may want to add this line at 114.

///////////      hspi1.Instance->SR = 0;    // tx 8 clock cycles to load receiver

///////////  we need to transmit before we can receive.

Posted on May 31, 2018 at 14:48

Please check the reference manual page 883, 3.2 Configuring the SPI in slave mode in DocID018909Rev 13

there is a check list,

can you see your incoming data changes as the clock is dropping.

thats either

CPOL = 1 and CPHA = 1;

or

CPOL = 0 and CPHA =0

Petr Sladecek
ST Employee
Posted on June 07, 2018 at 11:08

Hello,

I’m going back to begin of this thread to comment your polling example where can see few discrepancies at your code:

  • HAL_GPIO_ReadPin output should be compared rather with GPIO_PIN_RESET and GPIO_PIN_SET constants instead of 0,1
  • I don’t know your cpu frequency, but it would be nice to perform analysis what time sw spends by calling 4x HAL_GPIO_ReadPin function (you can try to toggle an auxiliary pin to see when the HAL_SPI_receive function is called). I would prefer in line assembly here to speed up the code.
  • HAL_SPI_receive is called with wrong parameters (pointer to hspi1 handle structure is missing, timeout set to zero produces immediate error output from the function – there is no test of any function output at your code).
  • HAL_SPI_receive is called when SCK signal is not at idle which is not suggested initialization of the slave by RM. This approach produces quite not defined start of the data reception (the function itself is written in common way and performs quite a lot operations before SPI is enabled). You can restore correct data from the received bit flow if begin of the transacted pattern is always constant
  • You can consider data packing and set reception threshold to 16 bit data. Then the polling sw works more relaxed.
  • If you want to use DMA you need to apply HAL_SPI_Receive_DMA and associate hspi DMA Rx handle but I believe it is not necessary for initial testing.

Hopefully this would be helpful information for you to continue in the project

Best regards,

Petr

Posted on June 08, 2018 at 14:08

Thank you Petr for reply. Actually i solved the problem, but it was test device where speed wasnt too high each clock was around 2us as you can see from the pictures. But real device has 50nanoseconds per clock. And here is a problem, it catches LOW on data and start reading  as i wants BUT seems like while MCU procceses the code with HAL_RECEIVE, we are loosing data, seems like HAL really slow, im loosing 2 bytes from the time when i catch zero on data, spi starts reading too late... THis is a code:

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == GPIO_PIN_RESET){} // wait until GPIOC 9 goes high

while (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_7) == GPIO_PIN_SET){}

 // 

wait until GPIOC 9 goes low

HAL_SPI_Receive(&hspi1, (uint8_t *)spi_Rxbuffer, 19, 2000);

  // read 19 bytes

Actually im not 100% sure that its 

HAL_SPI_Receive and not 

HAL_GPIO_ReadPin which causes this error. I tried to wait low on data with CMSIS register output which should be much faster, but i struggle with it., im waiting GPIOA.7 - 

while((GPIOA->IDR & 0x80) != 0x80) {} - doesnt know does it okay or not. Also i dont know why but after i initialize GPIO pins, IDR register holds 0x00000D40 value, i dont know why. How can i solve it?