2014-11-21 14 views
1

SPI 프로토콜을 통해 STM32L1 (NUCLEO-L152RE 보드)에 연결된 BlueNRG 칩 (확장 보드 X-NUCLEO-IDB04A1)과 통신하려고합니다.알 수없는 BlueNRG SPI 응답

BlueNRG manual에 따르면, 읽기/쓰기 버퍼 크기와 장치 상태를 얻기 위해 5 바이트의 빈 SPI 패킷 ((0x0B, 0, 0, 0, 0))을 보낼 수 있습니다. 장치가 잠자고 깨어있는 경우 상태는 0x02 (준비 됨)이거나 0x00 또는 0xFF이됩니다. 여기

내가지고있어 통신입니다 :

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를 사용하여 작성되었습니다. MCU는 기본 클럭 (MSI에서 2048 MHz)을 실행 중입니다.

// 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에서 수정 : 여기 SPI 초기화에 대한 책임이있는 코드입니다. 방법을 설명 이들 BlueNRG 반응을 치료하기 -

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

질문은 다음과 같이 보내기/코드가 구성되어 수신? 내가 사용하는 저수준 프로토콜에 대한 공식적인 설명을 찾을 수 없었습니다. 여기서는 HCI/ACI에 대해 말하지 않고 0x02 = 준비되지 않은 상태 코드에 대해서만 설명합니다. 하드웨어를 잘못 초기화하거나 여기에 명백한 내용이없는 경우도있을 수 있습니다. 어떤지도라도 감사 할 것입니다.

+3

나는이 하드웨어를 모르지만, 내가 아는 모든 SPI 구현은 동시에 보내고 받는다. 즉, SPI를 통해 바이트를 전송하면 한 번의 작업으로 바이트가 다시 전송됩니다. 당신은'spi' 객체가 응답을 버퍼링합니까? 그렇지 않다면 각각의 '0'을 기록한 후에 바이트를 읽어야한다. – UncleO

+0

정확합니다. 내 SPI는 아무 것도 버퍼링하지 않아서 동기식으로 읽고 쓸 필요가있었습니다. 고맙습니다! – kvark

답변

3

SPI 드라이버에 근본적인 문제가있는 것 같습니다. 들어오는 바이트가 저장되는 하드웨어 또는 소프트웨어에 버퍼가 있거나 어떻게 작동합니까? 일반적으로 전이중으로 SPI를 보내거나 수신하지 않습니다. 들어오는 데이터가 유효한지 또는 쓰레기인지를 SPI 드라이버 자체가 알 수 없기 때문에 "5를 보낼 때 2 바이트 만받습니다."와 같은 것은 없습니다. 항상은 5 바이트를 보낼 때 5 바이트를받습니다.

이 애플리케이션의 MCU는 SPI 마스터가되고 외부 칩은 슬레이브가됩니다. 전송 된 각 바이트에 대해 하나씩 수신하게됩니다. 그 바이트가 의미가 있는지의 여부는 외부 칩의 작동 방식에 달려 있습니다. 불행히도 SPI 표준은 없기 때문에 외부 칩은 예를 들어 "SCK & MOSI가 활성화되기 전에 슬레이브 선택을 x 시간 동안 낮추어야한다"와 같은 다양한 지연 요구 사항을 지정할 수있다. 외부 칩의 매뉴얼을 자세히 읽어야 할 것입니다.

그런 혼란이 모두 정리되면 SPI가 제대로 작동하지 않을 때 보통의 용의자가 있습니다 : 부정확 한 클럭 극성 또는 클럭 위상 설정으로 인한 클록 스큐.

+0

감사합니다! 동기식 데이터 전송은 매력처럼 작동했습니다. – kvark

1

제 5 장 : ST UM1865, SPI 인터페이스를 참조하십시오. BlueNRG-MS (BlueNRG 제외)이지만 HCI/ACI 인터페이스는 동일합니다.

처음 알았 듯이 첫 번째 바이트는 SPI READY 표시이며, 0x02는 슬레이브 SPI 인터페이스가 준비되었음을 나타냅니다. 0x02가 아닌 다른 값이면 마스터는 다음 4 바이트를 무시하고 SPI 트랜잭션을 중단해야합니다.

BlueNRG (또는 -MS) SPI가 준비한다면

(0x02로) 다음의 4 바이트 2 버퍼를 쓰기위한 크기를주고 읽어

가 가 은 (최대 값은 127 개의 기록 버퍼 크기
  • 2 바이트에 포함
      )
    • 네번째 바이트하여 예에서는 버퍼 사이즈

    읽어 포함 {0xB로, 0, 0, 0, 0} SPI 헤더 읽기 전용 버퍼의 크기 BlueNRG를 확인하는 것이다. 마찬가지로, {0xa, 0, 0, 0, 0}은 쓰기 버퍼의 크기를 확인하는 것입니다.

    예를 들어 {0x6, 0}의 예와 같이 반환되는 크기가 0이 아닌 경우대신 {0x6, 0, 0, 0}이어야합니다. 즉 BlueNRG를 6으로 읽을 준비가되었음을 의미합니다. (0 < < 8x06) 바이트의 데이터를 포함한다. 그런 다음 가능한 한 빨리 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를 참조하십시오.