2018-05-28 12:05 AM
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:
Clock is yellow and green is data.
I need only 16bytes from it, when data line goes low, we can see this 16bytes:
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.Solved! Go to Solution.
2018-05-29 02:47 AM
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
2)Zoomed up
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
2018-05-29 04:05 AM
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 bufferwhile(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 stringif ((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;
2018-05-29 08:00 AM
,
,
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
2018-05-29 11:49 PM
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
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)
{
}
}
2018-05-30 02:02 AM
What did you receive in the RXBuffer ?
2018-05-30 02:07 AM
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.
2018-05-30 02:50 AM
2018-05-30 03:39 AM
do you use the cube ?
it does work quite well.
I guess your config has issues.
2018-05-30 09:34 PM
Yes Cube, i keep it simple: no dma no interrupts
I chose CPOL low and CPHA 1 edge, because seems like master works in MODE 1, here is FE0010 data:
2018-05-31 05:25 AM
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