2025-01-15 07:14 PM - edited 2025-01-16 09:29 AM
I am writing sample demo Application to test data transfer between SPI Master(Nucleo F411RE) and SPI Slavee(Nucleo H755ZI-Q) device.
Master SPI:
/**SPI2 GPIO Configuration
PC2 ------> SPI2_MISO
PC3 ------> SPI2_MOSI
PB10 ------> SPI2_SCK
Slave SPI:
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
For validating what data Slave SPI device receiving over SPI I am sending this data over UART to display it on Host PC
Here is SLAVE SPI device UART response:
What I am seeing is that SPI receives wrong data instead of 0x41 (Send by master)
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Master SPI Code:
uint8_t message[1] = {0x41};
int counter = 0;
while (1)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_SPI_Transmit(&hspi2, message, 1, HAL_MAX_DELAY);
HAL_Delay(500);
counter++;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
SLAVE SPI code:
uint8_t txData[1] = { 0xAA }; // Data to send to the master
uint8_t rxData[1] = { 0x00 }; // Buffer to store received data
uint8_t tx_uart_buff[50];
while (1)
{
// Wait for data from the Master
if (HAL_SPI_Receive(&hspi1, rxData, 1, HAL_MAX_DELAY) == HAL_OK) {
// Data received successfully, respond to master
snprintf((char*)tx_uart_buff, sizeof(tx_uart_buff), "Slave Received SPI data: 0x%02X\r\n", rxData[0]);
HAL_UART_Transmit(&huart3,tx_uart_buff,sizeof(tx_uart_buff),10);
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); // Example: Toggle an LED
HAL_SPI_Transmit(&hspi1, txData, 1, HAL_MAX_DELAY); // Send response to the master
snprintf((char*)tx_uart_buff, sizeof(tx_uart_buff), "Slave Transmit SPI data: 0x%02X\r\n", txData[0]);
HAL_UART_Transmit(&huart3,tx_uart_buff,sizeof(tx_uart_buff),10);
} else {
snprintf((char*)tx_uart_buff, sizeof(tx_uart_buff), "Slave Receive SPI error\r\n");
HAL_UART_Transmit(&huart3,tx_uart_buff,sizeof(tx_uart_buff),10);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
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_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x0;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
I have also attached full Master and Slave CubeIDE Project.
If anyone can help me to figure out issue here as SPI Slave always reads wrong data.
@Andrew Neil @tjaekel @Peter BENSCH @B.Montanari
2025-01-15 11:45 PM - edited 2025-01-16 03:25 AM
The data received is the data you send. And what you send is the least significant byte of the address of "message" variable. That's what happens if you ignore the compiler warnings instead of fixing the problems with your code.
Correction - edited: you are sending some data from the address which least significant byte is stored in "message" variable.
Also, please read this topic:
2025-01-15 11:58 PM
Wouldn't TransmitReceive be a more appropriate method where you're concurrently collecting bits on the back edge of the clock that's pushing data out?
Observe what's going on over the wire with a logic analyze so you can visualize the interaction and relate it to the data you see and expectations.
2025-01-16 01:15 AM - edited 2025-01-16 01:25 AM
@gbm
yes that was an issue instead of sending data was sending Address
However after fixing that original issue still persist Slave receives wrong data:
SLAVE Data:
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
Slave Transmit SPI data: 0xAA
Slave Received SPI data: 0x60
2025-01-16 02:40 AM
You didn't fix the error - you've introduced another. Look at the compiler messages and fix the problem. First, get the code which compiles without warnings.
2025-01-16 09:10 AM
@gbm I have tried capturing variable using debugger after fixing compilation error ,still same issue and found that DR register not updating its value to 0x41
2025-01-16 10:00 AM - edited 2025-01-16 10:02 AM
Don't inspect the registers like this, it's invasive, reading DR clears bits in SR. It will also break FIFOs on models that have those.
Also DR is TWO registers at the same address, the data you write in there is NOT the data it reads back.
It's not a MEMORY cell, its a view on a more abstract and complex logic structure, if you looped back the MOSI to MISO you'd need to clock 8 times to see the same data returned on the input side.
Understand that SPI is a symetrical clocked interface, there's ONE clock source, as each bit shifts out and new bit shifts in.
2025-01-16 10:29 AM
With the version of SPI you use, the debugger can only rarely see the received data in DR. Don't open the debugger SPI register view during any transmission. Look at the values of program variables from variables. Still, you didn't show the updated code.
In the thread I referred you to, you may read why SPI slave is very hard to implement with an MCU unless the master side observes the timing constraints of the slave. Master-to-slave-only is easy, slave-to master is hard. Try Master to slave first.
2025-01-16 05:21 PM
@gbm what I am trying to test first is from Master to Slave only
-> Master sends one byte 0x41 to Slave , which I am expecting on Slave to receive it however I am receiving wrong data = 0x60
I have tried removing SPI_trasmit from Slave to Master , still same issue persists
Slave code:
uint8_t rxData[1] = { 0x00 }; // Buffer to store received data
uint8_t tx_uart_buff[50];
while (1)
{
// Wait for data from the Master
if (HAL_SPI_Receive(&hspi1, rxData, 1, HAL_MAX_DELAY) == HAL_OK) {
snprintf((char*)tx_uart_buff, sizeof(tx_uart_buff), "Slave Received SPI data: 0x%02X\r\n", rxData[0]);
HAL_UART_Transmit(&huart3,tx_uart_buff,sizeof(tx_uart_buff),10);
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); // Example: Toggle an LED
} else {
snprintf((char*)tx_uart_buff, sizeof(tx_uart_buff), "Slave Receive SPI error\r\n");
HAL_UART_Transmit(&huart3,tx_uart_buff,sizeof(tx_uart_buff),10);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
Slave Received SPI data: 0x60
Slave Received SPI data: 0x60
Slave Received SPI data: 0x60
Slave Received SPI data: 0x60
Slave Received SPI data: 0x60
Slave Received SPI data: 0x60
2025-01-16 07:34 PM
OK, jumping in a bit late.
My questions:
Could your provide an oscilloscope screenshot? (just to make sure MOSI comes out correctly from Master)
My suggestion:
Now configure and use a Slave device:
For me it looks like more as:
- your connection between Master and Slave has an issue, e.g.:
- MOSI - MOSI connection
- no external nCS connected (NSS mode)
- but wrong handling of SW NSS mode (forgotten to enable Slave Rx?!)
Just test in steps:
Even, you do not use any INT or DMA - you should be able to see a single byte received in the Slave DR register.
If not: potentially the slave was not enabled.
Even if you connect just SCLK (the Master Clock out) to a Slave (as Slave Clock in), but you leave MISO on Slave open: if you tie down now the Slave MISO (input) to 0 or VDD - you should get all 0x00 or 0xFF.
If this does not work --> your SCLK from Master to Slave does not work, or the Slave is not enabled (what I assume).