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

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

View solution in original post

25 REPLIES 25
S.Ma
Principal
Posted on May 28, 2018 at 09:37

Better use scope which can analyse/decode/log simple serial bus such as I2C or SPI.

https://www.keysight.com/en/pd-748302-pn-N5423A/ic-and-spi-serial-data-decode-option-for-infiniivision-6000-and-7000b-series-oscilloscopes?cc=FR&lc=fre

 
Posted on May 28, 2018 at 09:47

Well, my scope can do that. But the point that i need my stm32 catch this 16bytes data and  then output it on PC

Posted on May 28, 2018 at 09:51

Btw the images above is from my oscilo it catched the data and decode it, with chosen spi protocol on it. 

Posted on May 28, 2018 at 11:58

IMO the Cube/HAL code wouldn't manipulate SSI for the slave+softNSS case, so it will either start receiving as soon as enabled or never.

I don't Cube.

JW

Posted on May 28, 2018 at 12:41

 ,

 ,

Thanks for reply, what should i use then? Periph? CMSIS? Btw you said:

>,>,>, SSI for the slave+softNSS case, so it will either start receiving as

soon as enabled or never.

i puted NSS as hardware and pulled it down. So spi slave should start

receving

immediatly after it got first clocks. Why it doesnt happen?

2018-05-28 19:59 GMT+10:00 waclawek.jan <,st-microelectronics@jiveon.com>,:

STMicroelectronics Community

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

Re: STM32f407 as SPI slave[HAL]

reply from waclawek.jan

<,

MCUs Forum* - View the full discussion

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

Posted on May 28, 2018 at 14:57

i puted NSS as hardware and pulled it down. So spi slave should start

receving

immediatly after it got first clocks. Why it doesnt happen?

I don't know. Read out and check/post the content of SPI and relevant GPIO registers.

JW

Posted on May 28, 2018 at 15:06

You said that HAL is a bad idea for this task. What should i use instead?

StdPeriph?

2018-05-28 22:58 GMT+10:00 waclawek.jan <st-microelectronics@jiveon.com>:

STMicroelectronics Community

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

Re: STM32f407 as SPI slave[HAL]

reply from waclawek.jan

<

MCUs Forum* - View the full discussion

<https://community.st.com/0D70X000006SxywSAC

Posted on May 28, 2018 at 17:32

I try not to make recommendations in this regard.

My personal opinion is that any 'library' of this kind becomes a nuisance as soon as the task gets beyond usual or trivial, so it's better avoid them right away. I simply use the mcu's registers. But that view is here seen as extreme, and partially results from the nature of the work I do. Your may be different.

JW

Posted on May 28, 2018 at 20:07

'

You said that HAL is a bad idea for this task.'

any approach is a compromise of sort. that means anyone of them can be bad for at least one application. whether it is bad or not to your application is up to you.

I use both SPL (and liked it) and direct register access. because that has worked for me. hal is buggy and hard to think through vs. the datasheet.

others have found the opposite, however.

end of the day, use whatever that floats your boat.