I'm experiencing an issue with SPI communication between a Particle.io B524 and a slave module connected to my Dev Board.
When using an Arduino, the MISO line behaves correctly: it goes low when the CS line is low and stays low throughout the transaction. However, with the Particle.io B524, the MISO line stays high when the CS line is low.
Any suggestions on how to fix this?
My B524 is connected to a M2 Som Eval Board v.1.2
CS = Pin 34
MISO = Pin 36
MOSI = Pin 38
CLK = Pin 40
GND = Pin 42
/*
* Project myProject
* Author: Your Name
* Date:
* For comprehensive documentation and examples, please visit:
* https://docs.particle.io/firmware/best-practices/firmware-template/
*/
// Include Particle Device OS APIs
#include "Particle.h"
// Let Device OS manage the connection to the Particle Cloud
// SYSTEM_MODE(AUTOMATIC);
SYSTEM_MODE(MANUAL);
// Run the application and system concurrently in separate threads
SYSTEM_THREAD(ENABLED);
// Show system, cloud connectivity, and application logs over USB
// View logs with CLI using 'particle serial monitor --follow'
SerialLogHandler logHandler(LOG_LEVEL_INFO);
const int SPI_CS_PIN = D8; // Chip Select pin
const int DELAY_TIMER = 1; //
// Define command to be sent
const uint8_t COMMAND[] = {0x32, 0x00};
void setup()
{
// Set up SPI
SPI.begin(SPI_MODE_MASTER, SPI_CS_PIN);
SPI.setClockSpeed(1000000);
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
// Set up the chip select pin
pinMode(SPI_CS_PIN, OUTPUT);
digitalWrite(SPI_CS_PIN, HIGH); // Keep CS high initially
Serial.begin(9600);
delay(1000);
}
void loop()
{
// Send the initial command to the DW1001
digitalWrite(SPI_CS_PIN, LOW);
delay(DELAY_TIMER);
for (int i = 0; i < sizeof(COMMAND); ++i)
{
SPI.transfer(COMMAND[i]);
}
digitalWrite(SPI_CS_PIN, HIGH);
Serial.println("Sent initial command: 0x0C 0x00");
// Receive the response
uint8_t response[2]; // Adjust size if needed
digitalWrite(SPI_CS_PIN, LOW);
delay(DELAY_TIMER);
for (int i = 0; i < sizeof(response); ++i)
{
response[i] = SPI.transfer(0x00); // Send dummy byte to read response
}
digitalWrite(SPI_CS_PIN, HIGH);
// Process the received response
Serial.print("Received response: ");
for (int i = 0; i < sizeof(response); ++i)
{
Serial.printf("0x%02X ", response[i]);
}
Serial.println();
uint8_t values[20];
digitalWrite(SPI_CS_PIN, LOW);
delay(DELAY_TIMER);
for (int i = 0; i < 20; ++i)
{
values[i] = SPI.transfer(0x00); // Send dummy byte to read values
}
digitalWrite(SPI_CS_PIN, HIGH);
Serial.print("Received values: ");
for (int i = 0; i < sizeof(values); ++i)
{
Serial.printf("0x%02X ", values[i]);
}
Serial.println();
delay(2000);
}
Can you also share a trace of the Boron's behaviour during the read cycle? (like in your Arduino plot)
Also what device are you communicating with?
Is there a defined behaviour of the target device during "command transfer" that would suggest it would pull the line LOW?
IIRC the master is not obliged to pull the line low when it expects the slave to set the level on the line.
BTW, instead of performing multiple single byte transfers I'd go with the buffer transfer as shown here
Even when the impact is minimal with a 2-byte payload, I find the code more readable. With larger payloads the DMA access realy becomes handy.
I'd also like to note that SPI derives from the Stream class and hence also supports all its methods.
Thank you for all the feedback, it is still not working. I tried the buffer transfer method, but seems not to work on Arduino, so will give it a go later.
I am trying to connect to the DWM1001 from Qorvo. Qorvo DWM1001
I realize now I might have worked with different code sets on Arduino and Particle, but aligned them to be exactly the same. But what I find now is that MOSI is high in idle on particle, but low on Arduino.
The working and non-working traces in post 5 look identical to me. And in the original post, you said that MISO was high, and the post 5 that MOSI was staying high.
The B524 does not, and should not, drive the MISO pin when in master mode. It's in input mode and the slave device is what drives the pin when its CS pin is selected. If it's not going low, it's because the slave devices isn't driving it low as ScruffR mentioned.
Thank you for pointing that out. I realized I uploaded the same picture twice; I’ll correct it later today.
The main difference is that in the working example, MOSI is low in idle mode. My earlier comment about MISO being high was an observation, and I now understand it is controlled by the slave, so it isn’t crucial.
However, what puzzles me is that MOSI is high in idle mode, as seen in the images. Is this correct?
Could there be a difference in how the SPI library of Particle and Arduino work?
The state of MOSI does not matter when no CS pin is selected, because none of the slave devices are reading the bus (marked as xxxx in the diagram).
In mode 1, it's supposed to be low in idle state (after CS is low but before a clock cycle). The side that drives the data line does so on rising CLK and it's sampled by the other side on falling CLK.
Thank you @rickkas7 , @ScruffR for you help so far. I have updated my previous post with the correct images. Hope this helps clarify, and apologise for the confusion.
You cannot set the state of the MISO line. It's by definition only set by the SPI slave device when one is selected. It's indeterminate (floating) when not being driven by a slave device because SPI doesn't have pull resistors (unlike I2C).
You can't manually set the MOSI line using digitalWrite. It's controlled only by the SPI controller.
The state of MOSI when no devices are selected is also indeterminate, because SPI slave devices don't read it when not selected. What state it's in after beginning a transaction but before the SCK clocks in the first data bit is determined by the SPI mode. It's low in SPI mode 1.