in the datasheet, it's stated that I should apply 32 serial clocks to get the 32 bits of data. How can I program this is Arduino?

  • I suggest you to open the examples of the SPI library and check them. Anyway, the code should be byte result[4]; for (i = 0; i < 4; i++) result[i] = SPI.transfer(0x00); and you will find in result the 32 bits you need
    – frarugi87
    Apr 27 '16 at 12:45
  • I already did that. but the energy chip I am using is STPM10 and it suggests that I should use simplex synchronous SPI where the MOSI is not connected. there is just a timing diagram to switch from reading bytes and writing bytes. When I used SPI.transfer(), The data is not stable and I think not reliable Apr 29 '16 at 6:10
  • How do you say it is not reliable? The peripheral is full duplex, and according to the way it works the only way to receive data is by sending dummy data. If MOSI is not connected, well, it doesn't matter; note however that you can't use the MOSI pin for other tasks. By the way, did you remember to correctly set the slave select pin of the other peripheral? Did you use the SS pin on the arduino board or another one?
    – frarugi87
    Apr 29 '16 at 9:55

You call SPI.transfer() four times, each time saving the returned value to a variable after proper bit shifting.

uint32_t val;
val = SPI.transfer(0xff);  //0xff is a dummy
val |= (uint32_t)SPI.transfer(0xff) << 8;
val |= (uint32_t)SPI.transfer(0xff) << 16;
val |= (uint32_t)SPI.transfer(0xff) << 24;

I assume the least significant byte is received first. Make sure the SPI mode is the right one, as indicated in your datasheet.

If the slave can't handle being deasserted between bytes (which is what SPI.transfer() will do at the end of the transaction), then you can either try st2000's hardware SPI approach or use bitbanged SPI with shiftIn().

  • Not sure this will work. We really need to know how the SPI slave works before we can assume how it will react. Also, if the Chip Select line is asserted and de-asserted with each 8 bit SPI transaction, how well is the SPI slave designed? That is, such a SPI slave could easily get out of sync with the SPI master. Specifically, how are you assured which 8 bit byte you are actually reading?
    – st2000
    Apr 27 '16 at 14:13
  • @st2000 The OP saw fit to not give enough details; nothing but assumptions can be made till that changes. Apr 27 '16 at 14:59
  • All the examples I've seen use SPI,transfer(0) to read data rather than SPI.transfer(0xff). They also use SPI.transfer for writing data, too. I still haven't figured out what SPI does with the 0 or 0xff when you are actually reading data. Is this sent to the slave?
    – S. Imp
    Jun 20 '20 at 20:30
  • @S.Imp They're dummy bytes. You can send whatever you want to send, the device at the other end will still discard them, if it even pays the data any mind. SPI.transfer() is always used partly because of the intrinsic full-duplex nature of SPI and (as a result of the first factor) then partly because of the way most MCUs implement their SPI peripherals. Once the clock starts running, there is always "data" on the MOSI and MISO lines, it's just up to each participant on the bus to read it or not, deciding based on whatever predefined higher-layer protocol if the "data" is meaningful or not. Jun 23 '20 at 22:22
  • It wouldn't be totally incorrect to say you can't truly read without writing on an SPI bus and vice versa as well. So it makes sense to simply design a peripheral that takes a byte in one register and, 8 cycles later, returns a byte in another (or even the same) register, just to generalize usecases. Then it's up to the user's application to decide if they're only interested in the byte that was written out in the first place (TX) or the one that was read back (RX) or both (TX and RX). Also, hence the ambiguous name transfer() since it serves both reading and writing roles. Jun 23 '20 at 22:31

Sparkfun has a good explaination of what SPI is:

The Arduino IDE has a SPI library that comes with the IDE.

The library comes with two examples:
Using SPI to read a Barometric Pressure Sensor
Controlling a Digital Potentiometer Using SPI


Objective is to read 32 bits using the (unknown) device's SPI port.

If the device will tolerate the SPI Chip Select line activity (going from inactive to active to inactive for each 8 bit byte read) you should be able to get the desired 32 bits of data by performing 4 consecutive 8 bit SPI reads.

However, if the device will not tolerate the above SPI Chip Select line activity (that is, if the device requires the SPI Chip Select to be active for the entire 32 bit SPI transaction), you can not separate the 32 bit transaction into 4 individual 8 bit SPI transactions with out controlling the SPI Chip Select line. The following code example illustrates how this is done:

void loop(){
//transfer 0x0F to the device on pin 10, keep the chip selected
SPI.transfer(10, 0xF0, SPI_CONTINUE);
//transfer 0x00 to the device on pin 10, keep the chip selected
SPI.transfer(10, 0×00, SPI_CONTINUE);
//transfer 0x00 to the device on pin 10, store byte received in response1, keep the chip selected
byte response1 = SPI.transfer(10, 0×00, SPI_CONTINUE);
//transfer 0x00 to the device on pin 10, store byte received in response2, deselect the chip
byte response2 = SPI.transfer(10, 0×00);

The above example comes from the Arduino SPI library web page and is a 16 bit (not 32 bit) transfer. To code up a 32 bit transfer, continue to call the SPI.transfer method using the SPI_CONTINUE parameter.

added later...

It appears people are discouraging use of the DueExtendedSPI methods. And SPISettings and SPI.beginTransaction() are to be used? If so this page show example code where the code is explicitly controlling the SPI Chip Select line (look for slaveAPin & slaveBPin). Note how the code is reading 24 bits from slave A and writing 8 bits to slave B. To read 32 instead of 24 bits, we need to alter a segment of the code (along with a few other supporting changes) in this fashion:

  digitalWrite (slaveAPin, LOW);
  // reading only, so data sent does not matter
  val0 = SPI.transfer(0);
  val1 = SPI.transfer(0);
  val2 = SPI.transfer(0);
  val3 = SPI.transfer(0);
  digitalWrite (slaveAPin, HIGH);
  • We really need to see the specifications of the slave SPI device to compose a more specific answer.
    – st2000
    Apr 27 '16 at 13:26
  • I use STPM10 evaluation board. The connection is a simplex synchronous SPI, and the MOSI of the Arduino is not connected to anything. There is a timing diagram to switch from read only and write only. My problems is to how to read the data from the registers of the chip. I used SPI.transfer but I don't think the data is reliable. Apr 29 '16 at 6:04
  • The STPM10 timing diagram found on page 11 of it's spec does not look like a standard SPI transaction. I am inclined to say you can not use the Arduino SPI library. Instead, you may need to bit-bang this out totally in software. For instance, I do not believe there is a "SYN" line in the standard SPI bus. And I don't believe the Chip Select line should go high before the end of the SPI transaction.
    – st2000
    May 1 '16 at 2:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.