硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1518|回复: 4
收起左侧

[SPI/QSPI] STM32H723 HAL库 SPI 阻塞式接收无法阻塞问题

[复制链接]

1

主题

2

回帖

5

积分

新手上路

积分
5
发表于 2024-9-5 11:45:51 | 显示全部楼层 |阅读模式
HAL库版本为:V1.11.2,使用HAL_SPI_TransmitReceive函数发送和接收SPI数据,但直接将MOSI与MISO接口悬空,通过示波器可以测到MOSI、SCK数据线上均有数据,证明发送没问题。
但是MISO悬空,按道理应当阻塞1000ms,但是LED闪烁频率还是100ms,硬件调试发现,其不能实现阻塞功能;同理HAL_SPI_Receive函数也同样不能实现阻塞功能;
分析其阻塞原理,见图:

发现无论有MISO上有没有数据,SPI_SR寄存器的RXP位一直为1,理论上会硬件清零,但实际上不会。
因此,想请问各位大佬,是不是HAL库关于SPI阻塞的判断是有问题的?若有问题改如何修改呢?

以下是主函数以及SPI初始化函数:
main.C:
  uint8_t receiveBuff[32] = {0};
  uint8_t transimitBuff[32] = {0};
  memset(transimitBuff, 0xaa, 32);


  while (1)
  {
     HAL_SPI_TransmitReceive(&hspi1, transimitBuff, receiveBuff, 32, 1000);
     HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
     HAL_Delay(100);
  }
SPI.c:

SPI_HandleTypeDef hspi1;

/* SPI1 init function */
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 */
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  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.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  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_ENABLE;
  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 */

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI1;
    PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_CLKP;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{

  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspDeInit 0 */

  /* USER CODE END SPI1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_SPI1_CLK_DISABLE();

    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);

  /* USER CODE BEGIN SPI1_MspDeInit 1 */

  /* USER CODE END SPI1_MspDeInit 1 */
  }
}








回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-9-5 11:52:45 | 显示全部楼层
图片漏掉了,图片内容为HAL库SPI的接收判定:
        /* Check the RXP flag */
        if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXP))
        {
          *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint8_t);
          hspi->RxXferCount--;
          initial_RxXferCount = hspi->RxXferCount;
        }
位于STM32H7xx_hal_spi.c的1562-1569行。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117571
QQ
发表于 2024-9-6 09:24:02 | 显示全部楼层
主机没遇到过这种问题,从机遇到过问题。

我之前的测试是:主从机发起通信前,一定要保证主从机GPIO已经正确配置了SPI复用状态

测试的时候很容易出现主机的SPI还没有配置,就让从机进入了等待接收数据的状态,这个是不可以的,会导致从机接收一堆乱码。
回复

使用道具 举报

1

主题

2

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2024-9-7 19:27:16 | 显示全部楼层
问题解决了,因为我用的是软件片选,而我在主程序中未使能软件片选,导致无法阻塞;如果是硬件片选的话,不会有这个问题。
主程序修改如下:
        hspi1.Instance->CR1 |= 1<<11;
        HAL_SPI_Receive(&hspi1, receiveBuff, 8, 5000);
        hspi1.Instance->CR1 &= 0<<11;

就是在SPI接收之前,将SPI_CR1[SSI]位置1,使能SPI;接收完成后将SPI_CR1[SSI]置0,失能SPI;
最后,感谢大佬的解答!
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117571
QQ
发表于 2024-9-8 15:41:34 | 显示全部楼层
Muhe 发表于 2024-9-7 19:27
问题解决了,因为我用的是软件片选,而我在主程序中未使能软件片选,导致无法阻塞;如果是硬件片选的话,不 ...

谢谢告知最终问题原因。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-15 20:49 , Processed in 0.044096 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表