如何减少STM32L4 HAL库的SPI开销时间

问题描述 投票:1回答:2

我使用的是STM32L476RG板和HAL SPI功能:

HAL_SPI_Transmit(&hspi2, &ReadAddr, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi2, pBuffer, 4, HAL_MAX_DELAY);

我需要以最大速度从加速计的缓冲区接收数据,我在这些功能中遇到延迟问题。正如您在示波器屏幕截图中看到的那样,在几微秒内没有任何反应。我不知道如何最小化传输间隙。

enter image description here

我尝试使用HAL_SPI_Receive_DMA函数,这个延迟甚至更大。您是否知道如何使用HAL函数或任何有关如何在没有这些延迟的情况下编写SPI函数的指针来解决此问题?

accelerometer stm32 spi hal
2个回答
3
投票

TL; DR不要使用HAL,使用参考手册编写传输功能。

对于时间要求严格的任务(其中包括),HAL无可救药地过于复杂。只需看看HAL_SPI_Transmit()函数,它就超过60行代码,直到实际触及数据寄存器。即使没有多任务操作系统,HAL也会首先将端口访问结构标记为忙,验证功能参数,将它们存储在hspi结构中没有明显的原因,然后继续确定SPI所处的模式,等等。不需要在SPI主模式下检查超时,因为主控制所有总线时序,如果它在有限的时间内无法输出一个字节,那么端口初始化是错误的,周期。

没有HAL,它会更简单。首先,找出应该进入控制寄存器的内容,相应地设置CR1CR2

void SPIx_Init() {
    /* full duplex master, 8 bit transfer, default phase and polarity */
    SPIx->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE | SPI_CR1_SSM | SPI_CR1_SSI;
    /* Disable receive FIFO, it'd complicate things when there is an odd number of bytes to transfer */
    SPIx->CR2 = SPI_CR2_FRXTH;
}

此初始化假定Slave Select(NSSCS#)由单独的GPIO引脚处理。如果您希望SPI外设管理CS#,请在参考手册中查找从机选择(NSS)引脚管理。

请注意,全双工SPI连接不能只发送或接收,它始终同时进行。如果从器件需要一个命令字节,并且响应四个字节的数据,即5字节传输,则从器件将忽略最后4个字节,主器件应忽略第一个字节。

一个非常简单的传递函数

void SPIx_Transfer(uint8_t *outp, uint8_t *inp, int count) {
    while(count--) {
        while(!(SPIx->SR & SPI_SR_TXE))
            ;
        *(volatile uint8_t *)&SPIx->DR = *outp++;
        while(!(SPIx->SR & SPI_SR_RXNE))
            ;
        *inp++ = *(volatile uint8_t *)&SPIx->DR;
    }
}

通过使用SPI fifo,交错写入和读取,可以在需要时进一步优化它,以便发送器始终保持忙碌状态。

如果速度至关重要,请不要使用通用函数,或确保在执行时可以内联。使用启用了链接时优化的编译器,并优化速度(非常明显)。


3
投票

您可以使用HAL_SPI_TransmitReceive(&hspi2, ReadAddr, pBuffer, 1 + 4, HAL_MAX_DELAY);而不是HAL_SPI_TransmitHAL_SPI_Receive。这将避免发送和接收之间的时间。您还可以尝试更改编辑设置以优化速度。你也可以查看加速度计的数据表,也许你可以用一个框架读取所有的缓冲区,这就是这样的:HAL_SPI_TransmitReceive(&hspi2, ReadAddr, pBuffer, 1 + (4 * numOfSamples), HAL_MAX_DELAY);

© www.soinside.com 2019 - 2024. All rights reserved.