awy*_*lin 5 hal accelerometer spi stm32
我正在使用 STM32L476RG 板和 HAL SPI 功能:
HAL_SPI_Transmit(&hspi2, &ReadAddr, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi2, pBuffer, 4, HAL_MAX_DELAY);
Run Code Online (Sandbox Code Playgroud)
我需要以最大速度从加速度计的缓冲区接收数据,但这些功能存在延迟问题。正如您在示波器屏幕截图中看到的那样,有几微秒没有任何反应。我不知道如何最小化传输间隙。
我尝试使用 HAL_SPI_Receive_DMA 函数,这个延迟更大。您知道如何使用 HAL 函数或有关如何在没有这些延迟的情况下编写 SPI 函数的任何指针来解决此问题吗?
TL;DR 不要使用 HAL,使用参考手册编写你的传递函数。
HAL 对于时间紧迫的任务(除其他外)来说过于复杂。看看这个HAL_SPI_Transmit()函数,它有 60 多行代码,直到它真正接触到数据寄存器。即使没有多任务操作系统,HAL 也会首先将端口访问结构标记为忙碌,验证函数参数,hspi无缘无故地将它们存储在结构中,然后继续弄清楚 SPI 处于什么模式,等等。它不是在SPI主机模式下也需要检查超时,因为主机控制所有总线时序,如果在有限的时间内不能取出一个字节,那么端口初始化是错误的,周期。
没有HAL,事情就简单多了。首先,弄清楚应该进入控制寄存器的内容,CR1并进行CR2相应的设置。
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;
}
Run Code Online (Sandbox Code Playgroud)
此初始化假定 Slave Select(NSS或CS#)由单独的 GPIO 引脚处理。如果您希望CS#由 SPI 外设管理,请在参考手册中查找从设备选择 (NSS) 引脚管理。
请注意,全双工 SPI 连接不能只是发送或接收,它总是同时进行。如果从机需要一个命令字节,并以 4 个字节的数据作为应答,即 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;
}
}
Run Code Online (Sandbox Code Playgroud)
它可以在需要时进一步优化,通过使用 SPI fifo,交错写入和读取,以便发送器始终保持忙碌。
如果速度很重要,请不要使用通用函数,或者确保在使用时可以内联它们。使用启用链接时优化的编译器,并优化速度(很明显)。