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
Evgeny Popov
Associate III
Posted on May 29, 2018 at 11:47

i managed to synchronize slave and master with HAL function:

HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)spi_buffer, (uint8_t *)spi_buffer, 16, 2000);

Im sending from slave the bytes which i get from master, in purpose of debugging, and the data is same, so its perfectly synchronized and seems like slave reading all data master sends. Here is the images:

1) Slave is my STM32f4 and master that i catching, its the same

0690X00000602PTQAY.bmp

2)Zoomed up

0690X00000602WNQAY.bmp

The problem is that i dont know how to read that data, its 16bytes which i need somehow to read without slowing the spi down. All my attempts to do that are failed. The whole code are:

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 */

//while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != RESET){}

// while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != SET){}

// while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != RESET){}

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

uint8_t collect_bits[16] = {0};

char string_array[21] = {0};

uint8_t spi_buffer[16] ={0} ;

uint8_t flag_when_start_print = 0;

spi_buffer[0] = 5;

uint8_t spi_transmit[16] = {0};

HAL_SPI_Init(&hspi1);

while (1)

{

HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)spi_buffer, (uint8_t *)spi_buffer, 16, 2000);

}

}

The important fact that the beggining of the messge i want to catch is always starts with 0xFE0010, so after those bytes i need to read next 13bytes

T J
Lead
Posted on May 29, 2018 at 13:05

are you sending and receiving from the same buffer ?

I would suggest:

uint8_t spi_Rxbuffer[16] ={0}

uint8_t spi_Txbuffer[16] ={0}

there will be a flag to say HAL_SPI_TransmitReceive has completed. but its difficult to manage HAL sometimes.

I would use the register level coding style, I guess along these lines;

// initialise table

char RxTable[16];     

char RxCounter=0;

// clear RxSPI buffers  // not sure if its double buffered or not.

    while ((hspi1.Instance->SR  & SPI_FLAG_RXNE))

          RxSPI = hspi1.Instance->DR & 0xFF;   // dump old bytes in buffer

while(1){

while(RxCounter <16){

    while (!(hspi1.Instance->SR  & SPI_FLAG_RXNE))

         ;

        RxSPI = hspi1.Instance->DR;

// now you have 8 SPI clock cycles to do something with the data

   RxTable[RxCounter++] = RxSPI;

}

RxCounter =0;

// Process data within 8 SPI clock cycles or start losing bytes

}

// after thought:

// now consider that you may have lost coherency:

0xFE0010

is your string

   if ((RxSPI  == 0xFE)  && ( RxState =0)) RxState =1;

   else  if ((RxSPI  == 0x00) && ( RxState =1)) RxState =2;

   else  if ((RxSPI  == 0x01) && ( RxState =2))){

// check if we have been here before, that means we already have a complete set of data

if( RxCounter ==15)

   ; // we have complete data set in bytes RxTable[0..12]

// have start position.. start recording data

      RxCounter =0;

      RxState =0;   // reset state machine

   }

   else RxState =0;

Posted on May 29, 2018 at 15:00

 ,

 ,

Thank you a lot T J for helping, really appreciate that. As i

understand RxTable

read data in buffer from registers, then do the same all over again, btw if

i want to print those 16bytes through UART, can it cause off timings? ' if

((RxSPI == 0xFE) &,&, ( RxState =0)) RxState =1, ' - i think ill collect

13bytes after i get start positon then delinit spi and print data. Again,

thanks a lot ill give it a try

2018-05-29 21:06 GMT+10:00 T J <,st-microelectronics@jiveon.com>,:

STMicroelectronics Community

<,https://community.st.com/?et=watches.email.thread>,

Re: STM32f407 as SPI slave[HAL]

reply from T J

<,

MCUs Forum* - View the full discussion

<,https://community.st.com/0D70X000006SfIPSA0

Evgeny Popov
Associate III
Posted on May 30, 2018 at 08:49

Okay, the  HAL_SPI_TransmitReceive is really strange for me. for exmaple if i use  HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)spi_Txbuffer, (uint8_t *)spi_Rxbuffer, 16, 2000);

  outside of while(1) it should read 16bytes from master when it get first clocks and send 16bytes to master, this is how i see it. But what excatly i got 0690X00000602WSQAY.bmp

I used diffrent buffers as T J suggested, so tx_buffer sending 02 on every clock, why does it happening if i inisialize get and send 16bytes only once. 

/* USER CODE BEGIN 0 */

uint8_t spi_Rxbuffer[16] ={0};

uint8_t spi_Txbuffer[16] ={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};

char RxCounter=0;

/* USER CODE END 0 */

/**

* @brief The application entry point.

*

* @retval None

*/

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 */

//while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != RESET){}

// while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != SET){}

// while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) != RESET){}

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)spi_Txbuffer, (uint8_t *)spi_Rxbuffer, 16, 2000);

while (1)

{

}

}

Posted on May 30, 2018 at 09:02

What did you receive in the RXBuffer ?

Posted on May 30, 2018 at 09:07

you should single step, this is not trivial work. I cant do your work for you.

I already gave you a viable solution, I cant help more than that.

After a year of STM32 you wont need to ask any more questions.

199517CGIL4
Posted on May 30, 2018 at 10:39

do you use the cube ?

it does work quite well.

I guess your config has issues.

Posted on May 31, 2018 at 04:34

Yes Cube, i keep it simple: no dma no interrupts

0690X0000060L1WQAU.png0690X0000060L1vQAE.png0690X0000060L1qQAE.png0690X0000060L20QAE.png0690X0000060KtZQAU.png0690X0000060L21QAE.png

I chose CPOL low and CPHA 1 edge, because seems like master works in MODE 1, here is FE0010 data:

0690X00000602WOQAY.bmp
Posted on May 31, 2018 at 12:25

debugger shows me that we stuck at while (!(hspi1.Instance->SR  & SPI_FLAG_RXNE))

and Disassembly shows  0x8000D24 688A       LDR           r2,[r1, &sharp0x08]. 

But data is comming, RXNE flag should be SET