久芯网

如何减小HAL_SPI_Receive 函数的等待时间?

avatar stefan2005 提问时间: 2023-09-18 16:20:09 / 未解决
我想用stm32f303的两路SPI在4µs内各接收1个16bit 的数据,SPI SCK 18MHz 没毛病,但是两个HAL_SPI_RECEIVE 函数之间的等待时间却为惊人的8µs,竟然远大于<1µs 的信号传送时间,我的问题是,如何减小这个等待时间? 必须自己写底层函数吗?
SPI 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_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;[url=]Url[/url]
  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_ENABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }


测试放到main中的循环中
while(1)
{
uint16_t data_in;
HAL_SPI_Receive(&hspi1,(uint8_t *)&data_in,1,1);
}
下面是测试结果,时钟没问题 16 次, 18MHz. 但是两次接收之间的等待时间却是惊人的8µs.


13个回答
  • avatar lebment
    回答时间: 2023-09-18 16:49:16

    用DMA啊,没有别的,循环模式收

  • avatar 七哥
    回答时间: 2023-09-18 17:13:15

    不建议用同一片上的两路SPI互收发测试,最好用两块板一主一从测试,这样各干各的活。 不过单字节/单字收发的话,效率是很低,一个HAL_SPI_Receive函数,里面代码不少。

  • avatar stefan2005
    回答时间: 2023-09-18 17:35:13

    谢谢回复! 这里一次有16个时钟周期,所以是一次发16bit,我外接两个SPI接口的12bit ADC同时收数据,所以片子上开了两个SPI接口,想要在5µs的中断内接受数据,但是发现在限定的中断时间内没有完成下面的两道命令 HAL_SPI_Receive(&hspi1,(uint8_t *)&data_in_1,1,1); HAL_SPI_Receive(&hspi4,(uint8_t *)&data_in_2,1,1); 结果就把其中的一个函数放到main循环中看要执行多长时间。发现两次接受得16µs. 所以想问一下有没有办法把这个间隔等待时间缩短。

  • avatar stefan2005
    回答时间: 2023-09-18 17:57:22

    SPI 接口的初始化是CUBEMX生成的,所以想问一下数据接收的函数如何写可以和HAL SPI Init 匹配。

  • avatar MrJiu
    回答时间: 2023-09-18 18:22:16

    很正常,HAL内部API会有一系列的判断,这就会增加延时。换句话说就是API里面是:各种判断+正真的数据+各种判断。。。我没测试过正真数据前和后到底会需要多长时间,但是看描述的,应该就是8us了。要想改变这个,估计可能很难。。。

  • avatar MrJiu
    回答时间: 2023-09-18 18:51:34

    接上条回复。只能自己实现,但是,如果想程序稳定的话,估计也会需要一定的时间,估计也不会短。理由如下:F3系列时钟频率是72M,ARM指令周期,一个简单的指令应该是需要4个时钟(更具51来的,我百度没查到具体值,应该是差不多的),那么1us只能执行18条语句。10us,也就执行180条语句。所以你看自己项目对于两个SPI读取间隔需要的精度是多高?如果是1us,我感觉有点凉凉!!!

  • avatar MrJiu
    回答时间: 2023-09-18 19:19:35

    注意,如果是调用函数,还要包括入栈和出栈!!!所以,对于高精度要求,最好是换实现思路。。。

  • avatar stefan2005
    回答时间: 2023-09-18 19:36:26

    @MrJiu: 谢谢您的回复。看来我得精简API函数了,看能不能加速代码。 @lebment: DMA适用于单通道多次采样。我的项目里是双通道里同时采样两个数据后马上处理。单通道多次采样后再采样第二通道的数据时差更大。

  • avatar stefan2005
    回答时间: 2023-09-18 20:08:51

    这里给出解决方法,我用了stm32f4, 144MHz SCLK, 同样的代码跑了一次,只要3µs, 符合项目要求。 看来HAL函数需要执行快的系统时钟。再次验证了Mr. Jiu 的判断,函数执行快慢和系统时钟有关。

  • avatar 不咸不要钱
    回答时间: 2023-09-18 20:28:15

    这个之前也研究过,没找出来,楼主研究出来请告知一下谢谢,之前用NXP的MCU,这个时间间隔是可以调整的,当时用的时候还嫌弃就一个SPI,怎么还有这么多时间参数要调整 23333

  • avatar 陌路夕颜
    回答时间: 2023-09-18 20:51:08

    自己直接用寄存器写发送接收以及判断吧

  • avatar 水晶之泪0517
    回答时间: 2023-09-18 21:07:48

    代码执行效率太低了,直接使用寄存器操作试试

  • avatar butterflyspring
    回答时间: 2023-09-18 21:29:57

    库里面有LL层的方式,这样可以提高代码运行效率。不过需要用户熟悉硬件底层。如果楼主熟悉库函数的原理,或者可以考虑简单修改,只有把启动SPI的部分代码单独拿出来,这样就会大大缩短时间。当然注意不要改动出其他问题才行

会员中心 微信客服
客服
回到顶部