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

标签 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。但是,当我在此代码块的另一侧设置中断时,我看到 who00x5D 0xFF。它永远不会读取0x69。我查看了其他代码示例,有些人进行了第二次传输,并将数据设置为某个虚拟值(通常是 0xFF0x0),所以我也尝试了这一点,但是传感器在第二次尝试期间似乎感到困惑,who 最终成为 0x48。我已经尝试了等待我可以拥有的 RXNE/TXE/BSY 标志的每一种排列,以及许多其他要得到的东西变量正确读取SPI1数据寄存器,包括读取传感器的其他寄存器,但都无济于事。

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

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

我的分析仪屏幕显示传感器从单个读取请求发送回0x69,以及如果我尝试“虚拟传输”方法它发送的乱码。 Correcly sending me the WHO_AM_I value Sending back <code>0x48</code> on "double" transmit

最佳答案

传输时,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);

关于c - 读取STM32 MCU SPI数据寄存器的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51654627/

相关文章:

C - 制作数字比较程序时输出错误

c - C 中的表达式 "double (f)(double)"可能是什么意思

c - 为什么 ret 会随着优化而消失?

c - 由于我是嵌入式编程的新手,所以我无法理解 "%s\xC2\xB0"是什么?我知道 %s 是字符串

linux - linux下并口编程用什么简单的编程语言?

node.js - 使用 Galileo MRAA Node 控制伺服

c - 我应该在 CLion 中包含哪个库才能启用 readline

embedded - ISR 中过早出现 'return' 会发生什么?

c - C和嵌入式C有什么区别?

c - 它是如何制作从 poweron 到用户界面的 digicoder vcr dvd 播放器图形用户界面的?