未知的BlueNRG SPI响应

时间:2014-11-21 04:03:01

标签: embedded rust stm32 spi bluenrg

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

根据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();

zinc master稍微修改了SPI内部。发送/接收代码的组织如下:

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之外的状态代码)。我很可能只是错误地初始化硬件,甚至错过了一些明显的东西。非常感谢任何指导。

2 个答案:

答案 0 :(得分:3)

SPI驱动程序似乎有些根本错误。它是否在存储传入字节的硬件或软件中有缓冲区,或者它是如何工作的?通常,您不通过SPI发送或接收,收发全双工。 SPI驱动程序本身不可能判断输入数据是有效还是垃圾,因此没有"我发送5"时只收到2个字节。发送5个字节时,总是接收5个字节。

此应用程序中的MCU将是SPI主设备,外部芯片将成为从设备。对于发送的每个字节,您也将收到一个。该字节是否有意义取决于外部芯片的工作方式。遗憾的是没有SPI标准,因此外部芯片可以表示各种延迟要求,例如"在SCK& SCK&amp ;;之前,从机选择必须拉低x个时间单位。 MOSI上线"。您必须详细阅读外部芯片的手册。

然后当所有这些混乱被解决时,当SPI无法正常工作时,通常存在嫌疑:由于时钟极性或时钟相位设置不正确而造成时钟偏差。

答案 1 :(得分:1)

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

正如您所注意到的,第一个字节是SPI READY指示,0x02表示从SPI接口就绪。 如果它是0x02以外的任何值,则主机必须忽略以下4个字节并中止SPI事务。

如果BlueNRG(或-MS)SPI就绪(0x02),则以下4个字节给出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 <8 | 0x6)字节的数据。 然后,你应该尽快从BlueNRG读取6个字节。

请参阅功能BlueNRG_SPI_Read_All()的C:\ Program Files(x86)\ STMicroelectronics \ BlueNRG DK 2.0.2 \ Projects \ Drivers \ BSP \ STM32L1xx_BlueNRG \ SDK_EVAL_Spi_Driver.c。