读取STM32 MCU的SPI数据寄存器的值

时间:2018-08-02 13:14:58

标签: c embedded hardware stm32 spi

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

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。但是,当我在该代码块的另一端设置中断时,我看到who00x5D0xFF。它从不读取0x69。我查看了其他代码示例,然后有人进行了第二次传输,并将数据设置为某个虚拟值(通常为0xFF0x0),因此我也尝试过这样做,但是在执行过程中,传感器似乎感到困惑第二次尝试和who最终是0x48。我尝试了所有可能等待的RXNE / TXE / BSY标志的排列,以及许多其他事情来获取变量以正确读取{{1 }}数据寄存器,包括从传感器读取其他寄存器,但无济于事。

那么问题是,如何正确地从该寄存器读取值?

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

我在分析仪的屏幕上显示了传感器从单个读取请求中发回0xFF的情况,以及在尝试“虚拟传输”方法时传感器发送的乱码。Correcly sending me the WHO_AM_I value { {3}}

1 个答案:

答案 0 :(得分:3)

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

这是库不存在的问题。使用寄存器对SPI编程要容易得多。

我假设您的数据为8位。

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

 SPI1 -> CR2 |= SPI_CR2_FRXTH;

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

*(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库有什么意义。

代替

while (!LL_SPI_IsActiveFlag_RXNE(SPI1));

使用寄存器

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

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

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);