Skip to main content
Visitor II
August 8, 2022
Question

Unable to get SPI1 working on NUCLEO-F413ZH without using HAL

  • August 8, 2022
  • 5 replies
  • 1602 views

Hello,

Communication details (for now, the data transfer is only from master to slave):

(i) NUCLEO-F413ZH is the master

(ii) Arduino Uno R3 is the slave.

(iii) DFF is 8 bit

(iv) I want 2-line unidirectional

Using HAL: The SPI communication worked and I was able to print the transferred data on the serial monitor of Arduino IDE.

Without HAL: I don't know what the error is when I configure SPI1 on STM32 NUCLEO-F413ZH using registers. Nothing shows up on the serial monitor.

Please help me identify the error.

The code is as follows:

main.c - Ignore the gpio configuration of USB

#include "main.h"
SPI_HandleTypeDef hspi1;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
 
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_SPI1_Init();
 /* USER CODE BEGIN 2 */
 uint8_t tx_data = 8;
 uint8_t tx_data2 = 4;
 setupSPI();
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
//	 HAL_SPI_Transmit(&hspi1, &tx_data2, 1, 100);
	 sendData(tx_data);
	 HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_7);
	 HAL_Delay(2000);
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
 
/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
 /** Configure the main internal regulator output voltage
 */
 __HAL_RCC_PWR_CLK_ENABLE();
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 /** Initializes the RCC Oscillators according to the specified parameters
 * in the RCC_OscInitTypeDef structure.
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
 {
 Error_Handler();
 }
}
 
/**
 * @brief SPI1 Initialization Function
 * @param None
 * @retval None
 */
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_MASTER;
 hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
 hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi1.Init.NSS = SPI_NSS_SOFT;
 hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 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();
 }
 /* USER CODE BEGIN SPI1_Init 2 */
 
 /* USER CODE END SPI1_Init 2 */
 
}
 
/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 
 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 __HAL_RCC_GPIOG_CLK_ENABLE();
 
 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);
 
 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);
 
 /*Configure GPIO pin : USER_Btn_Pin */
 GPIO_InitStruct.Pin = USER_Btn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);
 
 /*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */
 GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
 /*Configure GPIO pins : STLK_RX_Pin STLK_TX_Pin */
 GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
 /*Configure GPIO pin : USB_PowerSwitchOn_Pin */
 GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);
 
 /*Configure GPIO pin : USB_OverCurrent_Pin */
 GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);
 
 /*Configure GPIO pins : USB_SOF_Pin USB_ID_Pin USB_DM_Pin USB_DP_Pin */
 GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
 * @brief This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
 /* USER CODE BEGIN Error_Handler_Debug */
 /* User can add his own implementation to report the HAL error return state */
 __disable_irq();
 while (1)
 {
 }
 /* USER CODE END Error_Handler_Debug */
}
 
#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @param file: pointer to the source file name
 * @param line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 

spi_test.h

// Define to prevent recursive inclusion
#ifndef __SPI_TEST_H
#define __SPI_TEST_H
 
/* This code tests SPI1. */
 
// Configuration functions
void setupSPI(void);
void sendData(uint8_t data);	// Using 8-bit data format
 
 
#endif // __SPI_TEST_H

spi_test.c

#include "stm32f413xx.h"
#include "stm32f4xx_hal.h"
#include "spi_test.h"
 
void setupSPI(){
 
	//	Resets SPI1 in peripheral reset register 2
//	RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;
 
	/* Configuring port A GPIO */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;	// Enables GPIOA clock for SPI1
	RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;		//	Enables SPI1 clock
 
	// Enabling GPIO pins -- Pins PA5 (SPI1_SCK), PA6 (SPI1_MISO), PA7 (SPI1_MOSI) and PD14 (SPI1_CS)
	GPIOA->MODER &= ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7);	// Clears the MODER5, MODER6 and MODER7 bits in GPIOA_MODER register
	GPIOA->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;// Sets the MODER bits to alternate functions
	GPIOA->AFR[0] |= GPIO_AFRL_AFRL5_0 | GPIO_AFRL_AFRL5_2;	// Sets alternate function 5 or 0101 i.e. bits 0 and 2 are high in AFRL register
 
	/* Configure SPI -- SPI_CR1 and SPI_CR2 registers */
	// Data frame format (DFF) bit in SPI1_CR1 register is 0 as 8-bit data format is used
	SPI1->CR1 |= SPI_CR1_SSM | (0x02UL << SPI_CR1_BR_Pos) | SPI_CR1_MSTR;
	SPI1->CR2 |= SPI_CR2_SSOE;
	SPI1->CR1 |= SPI_CR1_SPE;	// Enables the SPI bit in SPI1_CR1 register
 
 
}
 
void sendData(uint8_t data){
 
//	SPI1->DR |= data
//	HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_7);
//	while ((SPI1->SR & SPI_SR_TXE) != SPI_SR_TXE);
//	HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_14);
	while ((SPI1->SR & SPI_SR_TXE) == SPI_SR_TXE)
	{
		// Checks whether tx buffer is empty. Sending data stops when tx buffer is empty
		// (read reference manual pg-953 if confused)
		SPI1->DR |= data;
		HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_7);
	}
	if ((SPI1->SR & SPI_SR_BSY) == SPI_SR_BSY)
	{
		HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_14);
	}
}

    This topic has been closed for replies.

    5 replies

    Graduate II
    August 8, 2022

    The joys of register level, you've really got to own the debug.

    You'll want to dissect the HAL implementation, and the registers along the way.

    SPI1->DR |= data; // Pretty sure this is not kosher, different registers, and not memory

    Visitor II
    August 8, 2022

    I would start with 4 wire full duplex mode, even if not all spi signals are going to a gpio.

    Super User
    August 8, 2022

    Every time you are in doubt, start with reading out the registers and checking what's in them.

    > GPIOA->AFR[0] |= GPIO_AFRL_AFRL5_0 | GPIO_AFRL_AFRL5_2; // Sets alternate function 5 or 0101 i.e. bits 0 and 2 are high in AFRL register

    That's for PA5. PA6 and PA7 remained set to AF0.

    > SPI1->DR |= data; // Pretty sure this is not kosher, different registers, and not memory

    +1

    Also, get an oscilloscope, or at least a cheap logic analyzer.

    JW

    RIman.1Author
    Visitor II
    August 10, 2022

    Hello,

    Thanks a lot for replying.

    I made the changes but the Arduino still outputs garbage values on the serial monitor.

    main.c

    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_SPI1_Init();
     /* USER CODE BEGIN 2 */
     uint8_t tx_data = 8;
     uint8_t tx_data2 = 4;
     setupSPI();
     /* USER CODE END 2 */
     
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     /* USER CODE END WHILE */
    //	 HAL_SPI_Transmit(&hspi1, &tx_data2, 1, 100);
    	 sendData(tx_data2);
    	 HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_7);
    	 HAL_Delay(2000);
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */
    }
     
    /**
     * @brief System Clock Configuration
     * @retval None
     */
    void SystemClock_Config(void)
    {
     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
     
     /** Configure the main internal regulator output voltage
     */
     __HAL_RCC_PWR_CLK_ENABLE();
     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
     /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
     RCC_OscInitStruct.HSIState = RCC_HSI_ON;
     RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
     {
     Error_Handler();
     }
     /** Initializes the CPU, AHB and APB buses clocks
     */
     RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
     |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
     
     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
     {
     Error_Handler();
     }
    }
     
    /**
     * @brief SPI1 Initialization Function
     * @param None
     * @retval None
     */
    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_MASTER;
     hspi1.Init.Direction = SPI_DIRECTION_2LINES;
     hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
     hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
     hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
     hspi1.Init.NSS = SPI_NSS_SOFT;
     hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
     hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
     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();
     }
     /* USER CODE BEGIN SPI1_Init 2 */
     
     /* USER CODE END SPI1_Init 2 */
     
    }
     
    /**
     * @brief GPIO Initialization Function
     * @param None
     * @retval None
     */
    static void MX_GPIO_Init(void)
    {
     GPIO_InitTypeDef GPIO_InitStruct = {0};
     
     /* GPIO Ports Clock Enable */
     __HAL_RCC_GPIOC_CLK_ENABLE();
     __HAL_RCC_GPIOH_CLK_ENABLE();
     __HAL_RCC_GPIOA_CLK_ENABLE();
     __HAL_RCC_GPIOB_CLK_ENABLE();
     __HAL_RCC_GPIOD_CLK_ENABLE();
     __HAL_RCC_GPIOG_CLK_ENABLE();
     
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);
     
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);
     
     /*Configure GPIO pin : USER_Btn_Pin */
     GPIO_InitStruct.Pin = USER_Btn_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);
     
     /*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */
     GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
     
     /*Configure GPIO pins : STLK_RX_Pin STLK_TX_Pin */
     GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
     
     /*Configure GPIO pin : USB_PowerSwitchOn_Pin */
     GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);
     
     /*Configure GPIO pin : USB_OverCurrent_Pin */
     GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);
     
     /*Configure GPIO pins : USB_SOF_Pin USB_ID_Pin USB_DM_Pin USB_DP_Pin */
     GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
     
    }
     
    /* USER CODE BEGIN 4 */
     
    /* USER CODE END 4 */
     
    /**
     * @brief This function is executed in case of error occurrence.
     * @retval None
     */
    void Error_Handler(void)
    {
     /* USER CODE BEGIN Error_Handler_Debug */
     /* User can add his own implementation to report the HAL error return state */
     __disable_irq();
     while (1)
     {
     }
     /* USER CODE END Error_Handler_Debug */
    }
     
    #ifdef USE_FULL_ASSERT
    /**
     * @brief Reports the name of the source file and the source line number
     * where the assert_param error has occurred.
     * @param file: pointer to the source file name
     * @param line: assert_param error line source number
     * @retval None
     */
    void assert_failed(uint8_t *file, uint32_t line)
    {
     /* USER CODE BEGIN 6 */
     /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
     /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
     

    spi_test.c

    #include "stm32f413xx.h"
    #include "stm32f4xx_hal.h"
    #include "spi_test.h"
     
    void setupSPI(){
     
    	//	Resets SPI1 in peripheral reset register 2
    //	RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;
     
    	/* Configuring port A GPIO */
    	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;	// Enables GPIOA clock for SPI1
    	RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;		//	Enables SPI1 clock
     
    	// Enabling GPIO pins -- Pins PA5 (SPI1_SCK), PA6 (SPI1_MISO), PA7 (SPI1_MOSI) and PD14 (SPI1_CS)
    	GPIOA->MODER &= ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7);	// Clears the MODER5, MODER6 and MODER7 bits in GPIOA_MODER register
    	GPIOA->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;// Sets the MODER bits to alternate functions
    	GPIOA->AFR[0] |= GPIO_AFRL_AFRL5_0 | GPIO_AFRL_AFRL5_2 |
    			GPIO_AFRL_AFRL6_0 | GPIO_AFRL_AFRL6_2 | GPIO_AFRL_AFRL7_0 | GPIO_AFRL_AFRL7_2;	// Sets alternate function 5 or 0101 i.e. bits 0 and 2 are high in AFRL register
    	GPIOA->OTYPER &= (GPIO_OTYPER_OT_5 | GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);	// Sets pins 5, 6 and 7 in output type register to push-pull state
    	GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6
    			| GPIO_OSPEEDER_OSPEEDR7; // Output speed register is set to high speed
    	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD5 | GPIO_PUPDR_PUPD6 | GPIO_PUPDR_PUPD7); // No pull-up/pull-down
     
     
    	/* Configure SPI -- SPI_CR1 and SPI_CR2 registers */
    	// Data frame format (DFF) bit in SPI1_CR1 register is 0 as 8-bit data format is used
    	// Clock polarity is set to 0: '0' when idle
    	// Clock phase is set to 0 where the first clock transition is the first data capture edge
    	SPI1->CR1 |= SPI_CR1_SSM | (0x05UL << SPI_CR1_BR_Pos) | SPI_CR1_MSTR | (~SPI_CR1_CPOL) | (~SPI_CR1_CPHA);
    	SPI1->CR2 |= SPI_CR2_SSOE;
    	SPI1->CR1 |= SPI_CR1_SPE;	// Enables the SPI bit in SPI1_CR1 register
     
    }
     
    void sendData(uint8_t data){
     
    	while (!(SPI1->SR & SPI_SR_TXE));
    	SPI1->DR = data;
    	HAL_GPIO_TogglePin (GPIOB, GPIO_PIN_14);
    }

    Right now, I don't have access to oscilloscope and logic analyzer. Will purchase one as soon as possible.:grinning_face_with_sweat:

    Graduate
    August 9, 2022

    This will cause errors:

    while ((SPI1->SR & SPI_SR_TXE) == SPI_SR_TXE)

    Should be:

    while (!(SPI1->SR & SPI_SR_TXE)) ;

    SPI1->DR = data;

    while (!(SPI1->SR & SPI_SR_RXNE)) ;

    data = SPI1->DR;

    Super User
    August 9, 2022

    > This will cause errors

    Indeed. Sometimes it's hard to gather that "is empty" is in fact the flag being nonzero.

    > if ((SPI1->SR & SPI_SR_BSY) == SPI_SR_BSY)

    is suspicious, too, what was the intention? Btw. I generally recommend against using BSY, unless proven innocent in given STM32.

    JW

    RIman.1Author
    Visitor II
    August 10, 2022

    I was trying to experiment with the SPI_SR_BSY flag as it failed with the SPI_SR_TXE flag. Failed in both cases.