打印
[STM32H7]

SPI CLK响应较慢

[复制链接]
楼主: Hufei1994
手机看帖
扫描二维码
随时随地手机跟帖
41
belindagraham| | 2023-10-17 21:56 | 只看该作者 回帖奖励 |倒序浏览
如果SPI主从设备的通信速率不匹配,可能会导致SPI CLK响应较慢。

使用特权

评论回复
42
qiufengsd| | 2023-10-17 22:23 | 只看该作者
可能是SPI接收卡死问题,这可能会导致程序运行异常。

使用特权

评论回复
43
Hufei1994|  楼主 | 2023-10-18 08:55 | 只看该作者
belindagraham 发表于 2023-10-17 21:56
如果SPI主从设备的通信速率不匹配,可能会导致SPI CLK响应较慢。

我在俩个从设备上试过,分别是DRV8305和AMS5047P,都是这个现象。从设备的CLK是主设备发的为啥会不匹配呢?

使用特权

评论回复
44
Hufei1994|  楼主 | 2023-10-18 14:51 | 只看该作者
呐咯密密 发表于 2023-10-17 10:43
不用任何怀疑,是你的SPI发送函数有问题,在你的CS下拉之后,你并没有立刻传输数据,而是执行了各种校验工 ...

那这个是HAL库的正常现象了吧,实际传输时间是预期的3倍,效率有点低

使用特权

评论回复
45
Hufei1994|  楼主 | 2023-10-18 14:53 | 只看该作者
chenjun89 发表于 2023-10-17 19:46
几十个时钟周期也太夸张了吧,你是用的软片选还是硬片选。

软件写GPIO来控制的CS

使用特权

评论回复
46
Hufei1994|  楼主 | 2023-10-18 14:53 | 只看该作者
macpherson 发表于 2023-10-17 21:29
数据传输速率和 CLK 信号频率不匹配

CLK是主机给的怎么会不匹配呢?

使用特权

评论回复
47
Hufei1994|  楼主 | 2023-10-18 14:56 | 只看该作者
玄德 发表于 2023-10-13 19:50
往 SPI ->DR 寄存器写入数据,SCK 才会出现。
你的 CS 是用 IO 方式产生的,它的边沿和 SCK 没有任何关系 ...

软件写完CS就立刻运行SPI HAL函数了,但是是放在主循环里面跑的。实际再有个100us的中断在运行(运行时间大概在20us左右),可能是中断导致了SPI运行变慢嘛?

使用特权

评论回复
48
Hufei1994|  楼主 | 2023-10-18 14:59 | 只看该作者
呐咯密密 发表于 2023-10-17 10:43
不用任何怀疑,是你的SPI发送函数有问题,在你的CS下拉之后,你并没有立刻传输数据,而是执行了各种校验工 ...

// SPI发送读取函数
uint16_t SPI_ReadWrite_OneByte(uint16_t _txdata)
{

        HAL_GPIO_WritePin(SPI5_CS_GPIO_Port, SPI5_CS_Pin, GPIO_PIN_RESET);
        uint16_t rxdata;
        if(HAL_SPI_TransmitReceive(&hspi5,(uint8_t *)&_txdata,(uint8_t *)&rxdata,1,100) !=HAL_OK)
                {
                        rxdata=0;
                }
               
    HAL_GPIO_WritePin(SPI5_CS_GPIO_Port, SPI5_CS_Pin, GPIO_PIN_SET);
        return rxdata;
}
uint16_t AS5047_read(uint16_t add)
{
        uint16_t data;
        add |= 0x4000;        //读指令 bit14 置1
        if(Parity_bit_Calculate(add)==1) add=add|0x8000; //如果前15位 1的个数位偶数,则Bit15 置1
        SPI_ReadWrite_OneByte(add);                //发送一条指令,不管读回的数据
        data=SPI_ReadWrite_OneByte(NOP|0x4000); //发送一条空指令,读取上一次指令返回的数据。
        data &=0x3fff;
        return data;
}
代码是这么实现的,中间没有其他操作了

使用特权

评论回复
49
呐咯密密| | 2023-10-18 17:02 | 只看该作者
Hufei1994 发表于 2023-10-18 14:59
// SPI发送读取函数
uint16_t SPI_ReadWrite_OneByte(uint16_t _txdata)
{

问题在这个函数:HAL_SPI_TransmitReceive,你贴一下这个函数,这个函数在发送数据前应该是做了某些操作

使用特权

评论回复
50
呐咯密密| | 2023-10-18 17:21 | 只看该作者
Hufei1994 发表于 2023-10-18 14:59
// SPI发送读取函数
uint16_t SPI_ReadWrite_OneByte(uint16_t _txdata)
{
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  Transmit and Receive an amount of data in blocking mode.
  * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @param  pTxData: pointer to transmission data buffer
  * @param  pRxData: pointer to reception data buffer
  * @param  Size: amount of data to be sent and received
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
                                          uint32_t Timeout)
{
  uint32_t tickstart = 0U;
  HAL_StatusTypeDef errorcode = HAL_OK;

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  if (!((hspi->State == HAL_SPI_STATE_READY) || \
        ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->State == HAL_SPI_STATE_BUSY_RX))))
  {
    errorcode = HAL_BUSY;
    __HAL_UNLOCK(hspi);
    return errorcode;
  }

  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
  {
    errorcode = HAL_ERROR;
    __HAL_UNLOCK(hspi);
    return errorcode;
  }

  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
  {
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
  hspi->RxXferCount = Size;
  hspi->RxXferSize  = Size;
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
  hspi->TxXferCount = Size;
  hspi->TxXferSize  = Size;

  /*Init field not used in handle to zero */
  hspi->RxISR       = NULL;
  hspi->TxISR       = NULL;

  /* Set the number if data at current transfer */
  MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);

  __HAL_SPI_ENABLE(hspi);

  if (hspi->Init.Mode == SPI_MODE_MASTER)
  {
    /* Master transfer start */
    SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
  }

  /* Transmit and Receive data in 32 Bit mode */
  if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
  {
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* Check TXE flag */
      if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
      {
        *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
        hspi->pTxBuffPtr += sizeof(uint32_t);
        hspi->TxXferCount --;
      }

      /* Check RXWNE/EOT flag */
      if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_EOT)))
      {
        *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
        hspi->pRxBuffPtr += sizeof(uint32_t);
        hspi->RxXferCount --;
      }

      if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout))
      {
        /* Call standard close procedure with error check */
        SPI_CloseTransfer(hspi);

        /* Process Unlocked */
        __HAL_UNLOCK(hspi);

        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
        hspi->State = HAL_SPI_STATE_READY;
        return HAL_ERROR;
      }
    }
  }
  /* Transmit and Receive data in 16 Bit mode */
  else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
  {
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* Check TXE flag */
      if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
      {
        if ( (hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
        {
          *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint32_t);
          hspi->TxXferCount-=2;
        }
        else
        {
          *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint16_t);
          hspi->TxXferCount--;
        }
      }

      /* Check RXWNE/FRLVL flag */
      if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_FRLVL)))
      {
        if (hspi->Instance->SR & SPI_FLAG_RXWNE)
        {
          *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint32_t);
          hspi->RxXferCount-=2;
        }
        else
        {
          *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint16_t);
          hspi->RxXferCount--;
        }
      }

      if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout))
      {
        /* Call standard close procedure with error check */
        SPI_CloseTransfer(hspi);

        /* Process Unlocked */
        __HAL_UNLOCK(hspi);

        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
        hspi->State = HAL_SPI_STATE_READY;
        return HAL_ERROR;
      }
    }
  }
  /* Transmit and Receive data in 8 Bit mode */
  else
  {
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* check TXE flag */
      if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
      {
        if ((hspi->TxXferCount > 3U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_03DATA))
        {
          *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint32_t);
          hspi->TxXferCount-=4;
        }
        else if ((hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
        {
          *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint16_t);
          hspi->TxXferCount-=2;
        }
        else
        {
          *((__IO uint8_t *)&hspi->Instance->TXDR) = *((uint8_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint8_t);
          hspi->TxXferCount--;
        }
      }

      /* Wait until RXWNE/FRLVL flag is reset */
      if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_FRLVL)))
      {
        if (hspi->Instance->SR & SPI_FLAG_RXWNE)
        {
          *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint32_t);
          hspi->RxXferCount-=4;
        }
        else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_FRLVL_QUARTER_FULL)
        {
          *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint16_t);
          hspi->RxXferCount-=2;
        }
        else
        {
          *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
          hspi->pRxBuffPtr += sizeof(uint8_t);
          hspi->RxXferCount--;
        }
      }

      if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout))
      {
        /* Call standard close procedure with error check */
        SPI_CloseTransfer(hspi);

        /* Process Unlocked */
        __HAL_UNLOCK(hspi);

        SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
        hspi->State = HAL_SPI_STATE_READY;
        return HAL_ERROR;
      }
    }
  }

  /* Wait for Tx/Rx (and CRC) data to be sent/received */
  if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
  {
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
  }

  /* Call standard close procedure with error check */
  SPI_CloseTransfer(hspi);

       /* Process Unlocked */
  __HAL_UNLOCK(hspi);

  hspi->State = HAL_SPI_STATE_READY;

  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
  {
    return HAL_ERROR;
  }
  return HAL_OK;
}
这是我从STM32H743的HALL库里面找出来的的SPI发送接收函数,从你进入函数开始到真正将数据开始送出,前面经历了多少校验和查询,这写都会导致时钟延时。下面我贴寄存器方式的你看看,除了定义一个局部变量,之后马上使能SPI,然后会等待一个发送区空,然后立马向数据寄存器写值,此时时钟开始响应,开始发送数据。
u8 SPI2_ReadWriteByte(u8 TxData)
{                                   
        u8 RxData=0;       
        SPI2->CR1|=1<<0;                                //SPE=1,使能SPI2
        SPI2->CR1|=1<<9;                                  //CSTART=1,启动传输
       
        while((SPI2->SR&1<<1)==0);                //等待发送区空
        *(vu8 *)&SPI2->TXDR=TxData;                //发送一个byte,以传输长度访问TXDR寄存器   
        while((SPI2->SR&1<<0)==0);                //等待接收完一个byte  
        RxData=*(vu8 *)&SPI2->RXDR;                //接收一个byte,以传输长度访问RXDR寄存器       
       
        SPI2->IFCR|=3<<3;                                //EOTC和TXTFC置1,清除EOT和TXTFC位
        SPI2->CR1&=~(1<<0);                                //SPE=0,关闭SPI2,会执行状态机复位/FIFO重置等操作
        return RxData;                                        //返回收到的数据
}
如果你想更快,初始化的时候就使能SPI,不检测发送区,直接给TXDR送数据,就会更快的让时钟起来。自己测试就知道了。还是那句话,HALL库只能保证你的代码安稳的运行,并检测出在哪出错,但是实时性巨差,是所有方式里面最慢的。如果向高速运行代码,要学会交叉使用,需要快速就自己写寄存器。其他初始化可以用HALL

使用特权

评论回复
51
1988020566| | 2023-10-18 19:46 | 只看该作者
SPI接口的信号线连接不良可能会导致SPI CLK响应较慢。

使用特权

评论回复
52
pixhw| | 2023-10-18 20:25 | 只看该作者
SPI接口的时钟频率是SPI通信速度的关键因素之一,如果时钟频率设置过低,可能会导致SPI CLK响应较慢。

使用特权

评论回复
53
louliana| | 2023-10-18 20:56 | 只看该作者
SPI协议是一种同步串行数据协议,数据一位一位地传输,需要时钟线来同步。如果传输速度提高,则时钟频率也会提高,会导致硬件电路上的延迟,从而降低了SPI CLK的响应速度。

使用特权

评论回复
54
mnynt121| | 2023-10-18 21:17 | 只看该作者
没有正确配置SPI的时钟频率,或者没有正确初始化SPI。

使用特权

评论回复
55
eefas| | 2023-10-18 22:07 | 只看该作者
如果数据传输模式配置不正确,可能会导致响应时间变慢,需要检查数据传输模式的配置。

使用特权

评论回复
56
Hufei1994|  楼主 | 2023-10-18 23:04 | 只看该作者
呐咯密密 发表于 2023-10-18 17:21
这是我从STM32H743的HALL库里面找出来的的SPI发送接收函数,从你进入函数开始到真正将数据开始送出,前面 ...

感谢解惑,改日我使用寄存器来重写一下看看速度能否提升

使用特权

评论回复
57
呐咯密密| | 2023-10-19 09:14 | 只看该作者
Hufei1994 发表于 2023-10-18 23:04
感谢解惑,改日我使用寄存器来重写一下看看速度能否提升

测试完记得回来结贴,给问题一个答案

使用特权

评论回复
58
abotomson| | 2023-10-22 10:50 | 只看该作者
减小硬件电路延迟对SPI CLK响应速度的影响。

使用特权

评论回复
59
10299823| | 2023-10-22 11:44 | 只看该作者
可以优化程序结构,减少系统资源占用,提高响应速度。

使用特权

评论回复
60
modesty3jonah| | 2023-10-22 11:53 | 只看该作者
如果STM32单片机同时运行多个任务或程序,可能会导致系统资源占用过多,从而影响SPI接口的响应速度。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则