发新帖我要提问
12
返回列表
打印
[STM32F0]

关于SPI+DMA的使用问题

[复制链接]
楼主: chenyuanjiyi
手机看帖
扫描二维码
随时随地手机跟帖
21
chenyuanjiyi|  楼主 | 2021-12-2 17:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
呐咯密密 发表于 2021-12-2 17:10
关于两个数据之间的时间间隔不要用逻辑分析仪去抓,用示波器去抓,抓完拍照给我看一下。 ...

刚试完F103,发现用hal库,两包数据间距还是有13个us,目前手上只有逻辑分析仪,而且这个逻辑分析仪最大支持500M,我用F103配的18M,这个时钟基本是一直连上的,只能怀疑是HAL的运行效率更低了


snipaste_20211202_172449.png (160.47 KB )

snipaste_20211202_172449.png

snipaste_20211202_172125.png (206.02 KB )

snipaste_20211202_172125.png

使用特权

评论回复
22
呐咯密密| | 2021-12-2 17:31 | 只看该作者
chenyuanjiyi 发表于 2021-12-2 17:26
刚试完F103,发现用hal库,两包数据间距还是有13个us,目前手上只有逻辑分析仪,而且这个逻辑分析仪最大支 ...

我好像误会你的意思了,你的目的是加快两次SPI数据读取之间的时间是吧。这里的时间是DMA启动时间过长,这个是有办法解决的。你在代码里是连续采集的吗?中间有没有其他干扰,如果没有。你把HAL库所有的都换成寄存器操作。然后尝试自己去进件代码。有问题我明天上班给你解决,我先下班了。

使用特权

评论回复
23
chenyuanjiyi|  楼主 | 2021-12-2 17:46 | 只看该作者
呐咯密密 发表于 2021-12-2 17:31
我好像误会你的意思了,你的目的是加快两次SPI数据读取之间的时间是吧。这里的时间是DMA启动时间过长,这 ...

好的  谢谢啦
不是很理解你说的连续采集是啥意思,DMA配置为循环模式吗?
我DMA目前配置的是普通模式,至于寄存器操作,我现在基本都将他封装的进一步分解了,现在是直接对他定义的那些结构体操作了(离寄存器操作就差一步了),像这个DMA的通道配置
//    DMA_SetConfig(hdma_spi1_tx, SrcAddress, DstAddress, DataLength);
{
/* Clear all flags */
  hdma_spi1_tx.DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma_spi1_tx.ChannelIndex);

  /* Configure DMA Channel data length */
  hdma_spi1_tx.Instance->CNDTR = Size;

/* Memory to Peripheral */
//  if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
  {
    /* Configure DMA Channel destination address */
    hdma_spi1_tx.Instance->CPAR = (uint32_t)&hspi->Instance->DR;

    /* Configure DMA Channel source address */
    hdma_spi1_tx.Instance->CMAR = (uint32_t)pTxData;
  }
}

我现在再试试,还有点时间下班
首先还是要感谢大佬的帮忙,谢谢啦!

使用特权

评论回复
24
呐咯密密| | 2021-12-3 09:29 | 只看该作者
chenyuanjiyi 发表于 2021-12-2 17:46
好的  谢谢啦
不是很理解你说的连续采集是啥意思,DMA配置为循环模式吗?
我DMA目前配置的是普通模式,至 ...

看起来是没啥问题,现在你就是想缩短这个13.6us吗

使用特权

评论回复
25
chenyuanjiyi|  楼主 | 2021-12-3 09:42 | 只看该作者
呐咯密密 发表于 2021-12-3 09:29
看起来是没啥问题,现在你就是想缩短这个13.6us吗

恩恩  对的
HAL_StatusTypeDef HAL_SPI_MY_TransmitReceive_DMA0(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,uint16_t Size)
{
  HAL_StatusTypeDef errorcode = HAL_OK;
  static uint8_t Flag=0;
  /* Process locked */
//  __HAL_LOCK(hspi);

  /* Reset the threshold bit */
  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX);

  /* Set fiforxthresold according the reception data length: 8bit */
  SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);

  /* Enable the Rx DMA Stream/Channel  */
//  HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)pRxData, Size);
{
/* Disable the peripheral */
          hdma_spi1_rx.Instance->CCR &= ~DMA_CCR_EN;
         
          /* Configure the source, destination address and the data length */  
//          DMA_SetConfig(hdma_spi1_rx, (uint32_t)&hspi->Instance->DR, (uint32_t)pRxData, Size);
{
/* Clear all flags */
  hdma_spi1_rx.DmaBaseAddress->IFCR  = (DMA_FLAG_GL1 << hdma_spi1_rx.ChannelIndex);
  
  /* Configure DMA Channel data length */
  hdma_spi1_rx.Instance->CNDTR = Size;
  
  /* Peripheral to Memory */
  {
    /* Configure DMA Channel source address */
    hdma_spi1_rx.Instance->CPAR = (uint32_t)&hspi->Instance->DR;
   
    /* Configure DMA Channel destination address */
    hdma_spi1_rx.Instance->CMAR = (uint32_t)pRxData;
  }
}
          /* Enable the transfer complete, & transfer error interrupts */
          /* Half transfer interrupt is optional: enable it only if associated callback is available */
      hdma_spi1_rx.Instance->CCR |= (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);
         
          /* Enable the Peripheral */
          hdma_spi1_rx.Instance->CCR |= DMA_CCR_EN;

}
  
  /* Enable Rx DMA Request */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
  
  /* Enable the Tx DMA Stream/Channel  */
//  HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)pTxData, (uint32_t)&hspi->Instance->DR,Size);
{
/* Disable the peripheral */
          hdma_spi1_tx.Instance->CCR &= ~DMA_CCR_EN;
         
          /* Configure the source, destination address and the data length */  
//          DMA_SetConfig(hdma_spi1_rx, (uint32_t)&hspi->Instance->DR, (uint32_t)pRxData, Size);
{
/* Clear all flags */
  hdma_spi1_tx.DmaBaseAddress->IFCR  = (DMA_FLAG_GL1 << hdma_spi1_rx.ChannelIndex);
  
  /* Configure DMA Channel data length */
  hdma_spi1_tx.Instance->CNDTR = Size;
  
/* Memory to Peripheral */
  {   
    /* Configure DMA Channel destination address */
    hdma_spi1_tx.Instance->CPAR = (uint32_t)&hspi->Instance->DR;
   
    /* Configure DMA Channel source address */
    hdma_spi1_tx.Instance->CMAR = (uint32_t)pTxData;
  }
  
}
          /* Enable the transfer complete, & transfer error interrupts */
          /* Half transfer interrupt is optional: enable it only if associated callback is available */
      hdma_spi1_tx.Instance->CCR |= (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);

          HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
          /* Enable the Peripheral */
          hdma_spi1_tx.Instance->CCR |= DMA_CCR_EN;

}
  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
  }
  /* Enable the SPI Error Interrupt Bit */
  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));

  /* Enable Tx DMA Request */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);

error :
  /* Process Unlocked */
//  __HAL_UNLOCK(hspi);
  return errorcode;
}
这是我修改后的DMA_SPI的读写函数,几乎是操作寄存器了,结果两包数据间距还是有13.6us,采用F103使用这种方法也差不多有10几us,现在想缩短两包数据间的这个时间


使用特权

评论回复
26
呐咯密密| | 2021-12-3 09:52 | 只看该作者
你这个CSN的间隔这么长明显不是SPI的问题,是你有其他代码影响了两次SPI之间的时间,你的代码上传了没,我拉取一下看看

使用特权

评论回复
27
chenyuanjiyi|  楼主 | 2021-12-3 10:03 | 只看该作者
呐咯密密 发表于 2021-12-3 09:52
你这个CSN的间隔这么长明显不是SPI的问题,是你有其他代码影响了两次SPI之间的时间,你的代码上传了没,我 ...

上传上去了:https://github.com/Gu-Yue-Hu/SPI_DMA_HAL.git
master分支,这个后面要整理下,不太会玩
或者QQ:1364465583
谢谢啦

使用特权

评论回复
28
呐咯密密| | 2021-12-3 10:06 | 只看该作者

额,兄弟,你这while(1)里面有个延时啊,你这肯定会高的。你把这个延时删除

使用特权

评论回复
29
chenyuanjiyi|  楼主 | 2021-12-3 10:19 | 只看该作者
呐咯密密 发表于 2021-12-3 10:06
额,兄弟,你这while(1)里面有个延时啊,你这肯定会高的。你把这个延时删除
...

这个延时不是点灯的吗

最新的工程上传了 不能直接git clone 出来.....

可以加我QQ ,我发给你,github等后面再弄了

snipaste_20211203_101753.png (42.94 KB )

snipaste_20211203_101753.png

snipaste_20211203_101617.png (184.04 KB )

snipaste_20211203_101617.png

使用特权

评论回复
30
呐咯密密| | 2021-12-3 10:22 | 只看该作者
chenyuanjiyi 发表于 2021-12-3 10:03
上传上去了:https://github.com/Gu-Yue-Hu/SPI_DMA_HAL.git
master分支,这个后面要整理下,不太会玩
或 ...

另外有个概念需要搞清楚,DMA的启动时间是指你的CSN下降沿到你第一个CLK的上升沿/下降沿。

你把启动函数改为寄存器方式影响的是你的这个时间,而你的13.6us,是你的上一次dma处理完成到下一次DMA启动所耗费的时间,这个时间内如果你没有添加其他代码,那就是一个GPIO下拉所需的时间。

就类似我这个,就是在主循环里面只有一句DMA-spi的函数,所呈现的波形就是这样,两次DMA之间只有几百纳秒,而从CSN下拉到第一个CLK发出只有860ns。效率很高的。

使用特权

评论回复
31
chenyuanjiyi|  楼主 | 2021-12-3 10:22 | 只看该作者
呐咯密密 发表于 2021-12-3 10:06
额,兄弟,你这while(1)里面有个延时啊,你这肯定会高的。你把这个延时删除
...

去掉延时后的效果

snipaste_20211203_102124.png (11.31 KB )

snipaste_20211203_102124.png

使用特权

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

本版积分规则