cancel
Showing results for 
Search instead for 
Did you mean: 

interrupt on receiving bytes via SPI HAL

k.s.corp
Associate II

help me please. working in stm32cubeide. I can not enable interrupt on receiving bytes via SPI via HAL

main.c

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
 
/* USER CODE BEGIN PV */
uint8_t txb[1] = {0};
uint8_t rxb[1] = {0};
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_NVIC_Init(void);
/* USER CODE BEGIN PFP */
 
int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
 
  /* Initialize interrupts */
  MX_NVIC_Init();
 
  /* Infinite loop */
  while (1)
  {
	  asm("nop");
	  txb[0] = rxb[0] + 1;
  }
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** 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_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_NVIC_Init(void)
{
  /* SPI1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
 
static void MX_SPI1_Init(void)
{
  /* 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_HARD_INPUT;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
 
}
 
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, LD4_Pin|LD3_Pin, GPIO_PIN_RESET);
 
  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
 
  /*Configure GPIO pins : LD4_Pin LD3_Pin */
  GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
}
 
void Error_Handler(void)
{
 
}
 
#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
 
}
#endif /* USE_FULL_ASSERT */

stm32f0xx_it.c

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx_it.h"
 
extern SPI_HandleTypeDef hspi1;
 
void SPI1_IRQHandler(void)
{
  /* USER CODE BEGIN SPI1_IRQn 0 */
 
  /* USER CODE END SPI1_IRQn 0 */
  HAL_SPI_IRQHandler(&hspi1);
  /* USER CODE BEGIN SPI1_IRQn 1 */
 
  /* USER CODE END SPI1_IRQn 1 */
}

7 REPLIES 7
TDK
Guru

You'll need to start the transmission somewhere:

HAL_SPI_TransmitReceive_IT(&hspi1, txb, rxb, 1);

And then start it again after all (1) bytes are completed.

If you feel a post has answered your question, please click "Accept as Solution".
k.s.corp
Associate II

I think this is the wrong approach. An interrupt for this was done so that everything worked in hardware. My infinite loop should be empty. This is a slave, he expects signals from the master. If it is impossible to implement it otherwise, although I found information, but there they set up the controller directly through the registers.

I suppose normal interrupts were simply not delivered to HAL. On stm8 with the SPL library, not everything is smooth either, but I was able to cope, here I made interrupts for the UART and achieved the desired result

k.s.corp
Associate II

With an interrupt, it should work like this:

my program runs in an infinite loop, let it be:

while (1)
  {
          asm("nop");
	  txb = rxb;
	  asm("nop");
  }

and when the master starts the exchange with the slave, the program should get into the interrupt code:

void SPI1_IRQHandler(void)
{
 
  HAL_SPI_IRQHandler(&hspi1);
 
}

и уже зде�?ь �? должен вызывать �?ту функцию: HAL_SPI_TransmitReceive_IT(&hspi1, txb, rxb, 1);

but the program does not get into the interrupt code, no matter how hard the master tries to reach the slave. I suspect that you need to enable the receive interrupt, and most likely the environment does not support this, or it just needs to be done with cunning gestures

TDK
Guru

Yes, but you need to actually start reception prior to the main loop, otherwise the interrupt is not enabled and will never be called. HAL_SPI_Init doesn't start anything. There are other ways to do it, but if you want to do HAL with interrupts, that's the way.

If you feel a post has answered your question, please click "Accept as Solution".
k.s.corp
Associate II

Okay I will try. I will write what happens

k.s.corp
Associate II

I declare boldly that interrupts on HAL will not work as they should!!!

Piranha
Chief II

Yes, the HAL receive API is broken by design. It stops the reception all the time and you have to restart it... for a single byte. You cannot just enable the reception and then wait for new data of arbitrary amounts. The HAL team is just incapable of understanding and designing asynchronous software...