2021-12-14 07:35 AM
I am trying to get 2 stm32f411's to communicate via SPI. From my understanding, there should be 1 master device while the others should be its slaves.
For my master device, I am using full-duplex master and I have disabled NSS and enabled the NSS pin as an GPIO OUTPUT pin.
For my slave device, I am using full-duplex slave and have enabled NSS INPUT SIGNAL so it knows when it needs to read.
Here are my problems:
Here is a screenshot of the clock configuration I am talking about.
Here is the code for my master device:
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_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
uint8_t TX_Data[] = "abcdefgh";
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi2, TX_Data, sizeof(TX_Data), 5000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 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_1LINE;
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_64;
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 */
}
Here is the code for my slave device:
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_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
int8_t RX_Data[1652];
// Receive SPI Data (Blocking Mode) Polling
HAL_SPI_Receive(&hspi2, RX_Data, sizeof(RX_Data), 5000);
HAL_UART_Transmit(&huart1, RX_Data, sizeof(RX_Data), 5000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 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_SLAVE;
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_HARD_INPUT;
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 */
}
Also, please let me know if there are any good and detailed guides on spi, i2c, uart, etc.
Thank you very much for your time and help!
2021-12-14 09:48 AM
Hi,
the slave gets its clock from the master, you don't setup a slave clock.
Note that you are using blocking functions. I.e.sizeof(RX_Data) should match sizeof(TX_Data) for the beginning, or you will get a timeout (Receiver waiting for 1652 bytes to come).
Put the SPI releated code in the main loop such that sender and receiver meet, independently of boot order/timing.
If possible, use a (simple USB) logic analyzer for watching the signals.
hth
KnarfB
2021-12-14 10:43 PM
Use exti nss edge interrupt on the spave side to lock onto the incoming packet. Just imagine if you push the slave reset button few seconds after the master's....
Then use slave in dma ram tx and rx buffer dma cycic mode so slave can mostly avoid short latency interrupts. Once nss goes up on slave side, reset spi and dma and prepare the next data exchange. HAL doesn't provide EXTI on alternate function configured pin, register hack needed. Beware some stm32 slave max speed is div4 while master max speed is div2...
2021-12-15 10:24 AM
Hi, thank you for your advice. I have adjusted the sizeof(RX_Data) to 8 and now it outputs something. However, the output is garbage text and I'm not quite sure why.
"Put the SPI releated code in the main loop such that sender and receiver meet, independently of boot order/timing." I'm not quite sure what this means. Do you mean I should add the configurations for SPI2 in main()?
Once again, thank you for your help.
Edit: The garbage text I'm consistently getting is "È.. ...."
2021-12-15 10:30 AM
Hi, I'm not quite sure I understand what you mean. Maybe it's because I'm a beginner in stm32. How do I set exti nss edge interrupt and could you provide an example or elaborate a bit more on how to do this "Once nss goes up on slave side, reset spi and dma and prepare the next data exchange"? Thank you for your help!