【问题标题】:Unknown BlueNRG SPI response未知 BlueNRG SPI 响应
【发布时间】:2015-01-19 03:48:28
【问题描述】:

我正在尝试通过 SPI 协议与连接到 STM32L1(在NUCLEO-L152RE 板上)的 BlueNRG 芯片(在 X-NUCLEO-IDB04A1 扩展板上)进行通信。

根据 BlueNRG manual,我可以发送一个 5 字节的空 SPI 数据包:(0x0B, 0, 0, 0, 0) 以获取读/写缓冲区大小以及设备状态。状态应该是0x02(准备就绪),或者如果设备正在睡眠和正在唤醒,则为0x000xFF

这是我收到的信息:

Send (0x0B, 0, 0, 0, 0)
Receive (0x00, 0x00)    // why 2 bytes?
Send (0x0B, 0, 0, 0, 0) // assuming device is waking up, re-trying
Receive (0x06, 0x00)    // what is code 6?

我的测试应用是使用 Zinc 用 Rust 编写的。 MCU 正在运行默认时钟(来自 MSI 的 2048 MHz)。下面是负责SPI初始化的代码:

// PB.3 = CLCK
let _spi_clock = pin::Pin::new(pin::PortB, 3,
  pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
  pin::PullDown);

// PA.6 = MISO
let _spi_in = pin::Pin::new(pin::PortA, 6,
  pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
  pin::PullNone);

// PA.7 = MOSI
let _spi_out = pin::Pin::new(pin::PortA, 7,
  pin::AltFunction(pin::AfSpi1_Spi2, pin::OutPushPull, pin::Medium),
  pin::PullNone);

// PA.1 = CS
let spi_csn = pin::Pin::new(pin::PortA, 1,
  pin::GpioOut(pin::OutPushPull, pin::Medium),
  pin::PullUp);
spi_csn.set_high();

let spi = spi::Spi::new(spi::Spi1, spi::DirFullDuplex, spi::RoleMaster,
  spi::Data8b, spi::DataMsbFirst, 1); // baud pre-scaler = 2

let bnrg_reset = pin::Pin::new(pin::PortA, 8,
  pin::GpioOut(pin::OutPushPull, pin::VeryLow),
  pin::PullUp);

bnrg_reset.set_low();
// do something
bnrg_reset.set_high();

SPI 内部从zinc master 略有修改。发送/接收代码组织如下:

loop {
  spi_csn.set_low();
  // send a dummy read request
  spi.write(SpiRead as u8); // = 0x0B
  spi.write(0);
  spi.write(0);
  spi.write(0);
  spi.write(0);

  let status = spi.read();
  // debug print status
  while spi.has_more_data() {
    let data = spi.read();
    // debug print data
  }

  spi_csn.set_high();
}

问题是 - 如何解释或处理这些 BlueNRG 响应?我无法找到它使用的低级协议的任何正式描述(这里不是在谈论 HCI/ACI,而是关于0x02 = ready 以外的状态代码)。我很可能只是错误地初始化了硬件,或者甚至在这里遗漏了一些明显的东西。非常感谢任何指导。

【问题讨论】:

  • 我不知道这个硬件,但我知道的每个 SPI 实现都是同时发送和接收的。也就是说,通过 SPI 传输一个字节也会在一次操作中传输回一个字节。您是否spi 对象缓冲响应?如果没有,那么您应该在写入每个0 后尝试读取一个字节。
  • 你是对的。我的 SPI 没有缓冲任何东西,我需要同步读写。谢谢!

标签: embedded rust stm32 spi bluenrg


【解决方案1】:

请参考 STUM1865,第 5 章:SPI 接口。 它适用于 BlueNRG-MS(不是 BlueNRG),但 HCI/ACI 接口是相同的。

如您所见,第一个字节是 SPI READY 指示,0x02 表示从属 SPI 接口已准备好。 如果是 0x02 以外的任何值,主机必须忽略后面的 4 个字节并中止 SPI 事务。

如果 BlueNRG(或 -MS)SPI 已准备好(0x02),则以下 4 个字节提供 2 个缓冲区 读写大小:

  • 第 2 个字节包含写入缓冲区大小(最大值为 127)
  • 第 4 个字节包含读取缓冲区大小

在您的示例中,{0xb, 0, 0, 0, 0} 是 SPI 标头,仅用于检查 BlueNRG 的读取缓冲区大小。 同样,{0xa, 0, 0, 0, 0} 是检查写入缓冲区的大小。

如果返回大小不是 0,例如在您的示例 {0x6, 0} 中,我认为它应该是 {0x6, 0, 0, 0}, 这意味着 BlueNRG 已准备好读取 6 (0

BlueNRG_SPI_Read_All() 函数请参考 C:\Program Files (x86)\STMicroelectronics\BlueNRG DK 2.0.2\Projects\Drivers\BSP\STM32L1xx_BlueNRG\SDK_EVAL_Spi_Driver.c。

【讨论】:

    【解决方案2】:

    SPI 驱动程序似乎存在根本问题。它在存储传入字节的硬件或软件中是否有缓冲区,或者它是如何工作的?通常您不使用 SPI 发送或接收,而是以全双工方式收发。 SPI驱动本身将无法判断传入的数据是有效还是垃圾,所以不存在“发送5时我只收到2个字节”之类的东西。发送 5 个字节时,您总是收到 5 个字节。

    此应用程序中的 MCU 将是 SPI 主机,外部芯片将是从机。对于发送的每个字节,您也会收到一个。该字节是否有意义取决于外部芯片的工作方式。遗憾的是没有 SPI 标准,因此外部芯片可以说明各种延迟要求,例如“在 SCK 和 MOSI 生效之前,必须将从选择拉低 x 个时间单位”。需要详细阅读外置芯片的说明书。

    然后,当所有的困惑都被解决后,当 SPI 无法正常工作时,当然会有常见的怀疑:由于不正确的时钟极性或时钟相位设置而导致的时钟偏差。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-12
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多