本文介绍了读取STM32 MCU的SPI数据寄存器的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有很多类似的问题,但似乎没有一个完全相同的问题。我正在将STML4 MCU连接到6轴传感器(LSM6DS3)。我已经在I2C中成功实现了所有功能,但是希望SPI(和DMA,如果我可以使这些第一步工作正常……)的额外速度。因此,第一步,我尝试读取设备的 WHO_AM_I 寄存器( 0x0F ),该寄存器应进行答复使用 0x69 。这是代码:

There are quite a few similar questions, but none seem to have quite the same issue. I am connecting an STML4 MCU to a 6-axis sensor (LSM6DS3). I have successfully implemented everything in I2C, but would like the extra speed of SPI (and DMA, if I can get these first steps working...). So for a first step, I am trying to read the WHO_AM_I register (0x0F) of the device, which should reply with 0x69. Here is the code:

uint8_t who = 0;

// Sanity check/debugging aid should get 0x5D
who = 0x43 + 0x1A;

// Set SS low
GPIO_WritePin (GPIOB, LL_GPIO_PIN_7, GPIO_PIN_RESET);

// while tx buffer is in use, wait
while (!LL_SPI_IsActiveFlag_TXE(SPI1));

// Send READ command to the WHO_AM_I register
(SPI1->DR) = 0x8F;

// while rx buffer is in use, wait
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));

// Get data off the register
who = (SPI1->DR);

// Wait for everything to wrap up before setting SS high again
while (LL_SPI_IsActiveFlag_BSY(SPI1));

// OK, now we can set SS high
GPIO_WritePin (GPIOB, LL_GPIO_PIN_7, GPIO_PIN_SET);

在示波器/分析仪上,我看到一切都按预期运行,包括传感器发回 0x69 。但是,当我在此代码块的另一端设置中断时,我看到 0 变为 0x5D 0xFF 。它从不读取 0x69 。我查看了其他代码示例,有人再次发送了数据,并将数据设置为某个虚拟值(通常 0xFF 0x0 ),所以我也尝试过,但是传感器似乎在第二次尝试中感到困惑,并且最终变成了 0x48 。我尝试了所有等待 RXNE / TXE / BSY 标志以及许多其他东西,以使变量正确读取 SPI1 数据寄存器,包括从传感器读取其他寄存器,但是

On the scope/analyzer, I see everything run as expected, including the sensor sending back 0x69. However, when I set a break on the other side of this code block, I see that who goes from 0 to 0x5D to 0xFF. It never reads the 0x69. I looked through other code examples and some people have a second transmit with the data set to some dummy value (usually 0xFF or 0x0), so I also tried that, but the sensor seems to get confused during the second attempt and who ends up being 0x48. I have tried every permutation of waiting for the RXNE/TXE/BSY flags that I could have, as well as many many other things to get the variable to correctly read the SPI1 data register, including reading other registers off the sensor, but all to no avail.

因此,问题是,如何正确读取该寄存器的值?

So then the question is, how does one correctly read values off this register?

我还应该提到我可以成功写入设备的寄存器。我可以发送我想要的命令,然后将其读回并看到它在作用域内正常工作,即使我永远无法在代码中获得分配给变量的值。我总是得到 0xFF

I should also mention that I can successfully write to the device's registers. I can send the command I want, then read it back and see that it worked on the scope, even though I can never get the values assigned to a variable in code. I always get 0xFF.

我包括分析仪的屏幕,显示传感器发回 0x69 ,以及如果我尝试虚拟传输方法时发送的乱码。

I include a screen of my analyzer showing the sensor sending back 0x69 from a single read request, as well as the garbled mess it sends if I try the "dummy transmit" method.

推荐答案

SPI始终(如果启用了接收器),则在传输时会接收到数据。

SPI always (if the receiver is enabled) receives the data when you transfer.

这是您不知道其中存在库的问题。 SPI使用寄存器更容易编程。

This is the problem with the libraries that you do not know what is there. SPI is a lot easier to program using registers.

我假设您的数据为8位。

I assume that your data is 8bits.

您需要可以通过以下方式在SPI初始化期间设置1/4(一个字节)的FIFO阈值:

You need to set the 1/4 (one byte) FIFO threshold during the SPI initialization by:

 SPI1 -> CR2 |= SPI_CR2_FRXTH;

接下来,您需要在每次写操作后从FIFO中读取数据(还需要强制编译器以使用正确的大小(在这种情况下为8位)加载和存储指令):

next you need to read the data from the FIFO after every write (you need also to force the compiler to use the correct size (in this case 8bits) load and store instructions):

*(volatile uint8_t *)&SPI1->DR = 0x8F;  // write exactly 8 bits to the FIFO
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
dummy = *(volatile uint8_t *)&SPI-> DR;
*(volatile uint8_t *)&SPI1->DR = 0;  // dummy write
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
who = *(volatile uint8_t *)&(SPI1->DR);

我不知道使用LL库有什么意义。

I do not know what is the point of using the LL libraries.

而不是

while (!LL_SPI_IsActiveFlag_RXNE(SPI1));

使用寄存器

while (!(SPI1 -> SR & SPI_SR_RNE));

您也可以将其包装到函数中:

You can also wrap it into the function:

uint8_t SPI_ReadWrite8(SPI_TypeDef *spi, uint8_t data)
{
    while(!(spi -> SR & SPI_SR_TXE));
    *(volatile uint8_t *)&spi->DR = data;
    while (!(spi -> SR & SPI_SR_RNE));
    return *(volatile uint8_t *)&spi-> DR;
}

SPI_ReadWrite8(SPI1, 0x8f);
who = SPI_ReadWrite8(SPI1, 0);

这篇关于读取STM32 MCU的SPI数据寄存器的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 17:28
查看更多