Full Duplex SPI on XBee modules

All of my experience with SPI to date has been effectively half-duplex: the Master sends the known-size command (ignoring the data received from the Slave), then when it receives an interrupt from the Slave it re-starts the clock and sends known-sized garbage and receives the known-sized reply.

I am looking at embedding the XBee SX into a project, and since the MCU only has a spare SPI port I’d use that. So I read the docs and noted the diagram and description here:

SPI is inherently bit-synchronous; the byte boundaries are not explicit, but the start of transmission or reception implicitly defines them - when operating in half duplex. However, the above full-duplex description implies that the XBee can start transmitting on any bit boundary, not on a multiple of eight. It indicates that it has started by asserting nATTN, and finishes by de-asserting nATTN. Indeed, the above diagram asserts nATTN after the 5th clock. (At first I thought that nATTN was effectively an IRQ from the XBee to say that it had data, so please start clocking. But the above diagram explicitly shows this is not the case.)

This post https://forums.digi.com/50914/xbee-wifi-s6b-spi-bug seems to describe exactly this phenomenon. The poster gives an example of the 0x7E start byte being shifted as 0xFC, since byte boundaries were assumed.

That post also alludes to the other implication of the above: how many clocks should the Master send? It can’t send just the number sufficient to clock out its request: the XBee could have started to reply, so the Master needs to keep clocking until the Slave has finished. Again, the above diagram shows exactly this, with the Master still sending garbage after it has finished, and not de-asserting nSSel until the Slave is done.

Given that the API is not fixed-size (although each individual command’s response may well be, but that’s not explicitly stated), and that no other SPI implementation in my experience uses a signal like nATTN to “bracket” the Slave’s reply, it appears as though I cannot use the MCU’s SPI hardware. I’ll have to software bit-bang the interface, examining and tracking nATTN on every bit to determine if the XBee is replying or not, shifting each data bit manually since they’re not on byte boundaries, and keeping nSSel asserted and clocking until the Slave is finished.

I might be able to use the SPI hardware if I tell it to expect a huge receive. Either:

  • The transmission finishes without nATTN, in which case I abort the receive;
  • nATTN is asserted during the transmission, and I reset the Receive side mid-byte(!), then when nATTN is de-asserted I again abort the Receive.
    Either way, no DMA is possible!

Or have I completely over-thought all of this, and of course the XBee’s SPI is byte-oriented, the above diagram notwithstanding?

With thanks for any information,


1 Like

I’ve started working on this too, using an ESP32 in SPI_Master mode, and I was confronted to the same kind of issues. I’ve not yet been faced with receiving something while trying to send to the xbee though, which would supposedly occur if ATTN was asserted while sending.

My issue so far was mostly that I tried to get the size of the frame, and then read the proper number of bytes in a subsequent transaction, but then I had already lost the data and got only zero. My solution so far, as you suggested too, was to receive a large size packet (with the size mostly based on what I expected) right after sending a frame to the xbee, then check the packet for validity, size, data and checksum.

I honestly wish there would be a way to switch the xbee to half-duplex SPI that would definitely simplify things and make it more “to the de facto norm”…

If ever you built some sort of a working protocol to handle full duplex, please let me know