2022-08-08 10:25 AM
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);
}
}
2022-08-08 10:32 AM
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
2022-08-08 10:46 AM
I would start with 4 wire full duplex mode, even if not all spi signals are going to a gpio.
2022-08-08 12:14 PM
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
2022-08-09 12:42 AM
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;
2022-08-09 02:04 AM
> 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
2022-08-10 10:16 AM
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:
2022-08-10 10:18 AM
I was trying to experiment with the SPI_SR_BSY flag as it failed with the SPI_SR_TXE flag. Failed in both cases.