I am trying to write a byte (Register address) to an accelerometer SPI slave to get the value of this register in the same tranfer.
As I understand the code of the function -> spi_transfer(SPI_dev,Tx_buff,Rx_buff,size), The first byte in the TX_buff must be the register address of the slave and I have to set the next bytes of this buffer to 0xFF to do “as if” Nothing was transfered after the first byte(In the fact, there is a tx followed by a rx before incrementing the “transfer byte”).
It doesn’t works as I want! It returns Something like -22 or Something like the number of bytes transfered (seems to be like). But the return value must be 0 if all run successful…
In the first param of the function, I just wrote SPI0 (there is only one generic spi device)
I am wondering if it is possible to do like that. …Or is it not possible to do a 1 byte write followed by a multibyte read in one transaction? Without /CS going high in the mean time?
Thanks for the help!
Are you trying to connect two SPI Slave devices together? If so, that is not going to work. One of the two devices has to support SPI Master mode. Since the XBee module does not, your processor you use needs to support that.
In addition, all data going in and out of the SPI port of an XBee module will be and needs to be in the Digi XBee API format.
Thank you for the answere. No, I am not trying to connect two slave devices, but yes, programmable xbee modules can work as SPI master. In the programmable version, there is a Freescale uC which has a SPI module for slave and master operations. The pins are routed outside of the module.
In the fact, as mentionned in the digi firmware user guide : http://xbee-sdk-doc.readthedocs.io/en/1.5.7/api_doc/pg/ , the xbee module can only be used in SPI master mode (with the firmware library)
Then, I want to know (in addition of the questions in my first post), where can I find the name of my slave device, to put it as first parameter of the spi_transfer function?
Thanks in advance.
I was unable to do the transfer I wanted using the spi_transfer function, then I wrote this :
void my_func_read(uint8 reg, char* p_rd_data , uint8 size)
/* Wait until tx buffer is empty /
SPI1D = reg;
while (size-- > 0)
SPI1D = 0xFF;
/ Wait until rx buffer is full */ while(!SPI1S_SPRF);
*(p_rd_data++) = SPI1D;
Where the user has to replace XPIN_12 with the one he uses for the chip select signal.
It send one byte (here the slave’s register address) and then stores “size” bytes of data comming from the slave in the buffer p_rd_data. In my case, it set the address pointer of the spi slave to the address I want to read from and then it reads the successives values at successives addresses.
ALL of the Programmable XBee modules that offer SPI are only SPI Slave and not Master. This is a hardware limitation and not something that you can change in Code.
The S2C Programmable module has a HCS08 microcontroller build inside. Its spi module can be used in master mode using the registers SPIxD, SPIxS, SPIxBR, SPIxC1 and C2.
Additionaly, if you take a look here http://xbee-sdk-doc.readthedocs.io/en/1.5.7/api_doc/pg/ you will see that this api only implements master mode. This api is the one you get from digi in the xbee plugin for the eclipse sdk.
Finaly, my spi slave is now working fine with my programmable module. I CAN NOT belive that there is no possibility of using a programmable xbee module as spi master since mine is working fine…
There was a problem in the code above. In the spi module, there are two registers for writing to and reading from spi. They are different registers but both are accessed by reading or writing the SPIxD register. The tx register is transfered to the shift register as soon as there is room for it, signaled by the bit SPI1S_SPTEF. As soon as this bit is 1 and that you put data in the tx register, the data is shifted out to the MOSI pin. In the same time, data is shifted in the same shift register from the MISO pin. When the transfer is completed, the 8 bits shifted in are transfered in the RX register, but only if the rx register is free. If not, data is discarded.
To free the rx register, one have to 1) read the SPI1S_SPRF flag and 2) read the SPIxD register.
Then, I did it in this new lines of code :
void myFunct(uint8 reg, char* p_rd_data, uint8 size)
uint8 eraser;//for dummy reads to erase the rx reg content.
gpio_set(XPIN_12,FALSE);//chip select pin
while(!SPI1S_SPTEF);//No tx can be done if SPI1S_SPTEF is set
SPI1D = reg;//writing reg into SPI1D initiate the transfer (out and in)
while(!SPI1S_SPRF);//wait for the dummy rx byte in rx register to free it
eraser = SPI1D;//as specified in datasheet, flag + data regs must be read to erase the content of the rx register
SPI1D = 0xFF;//since this function is reading data from the spi slave, write 1 in the output to make as if nothing is going out…
while (!SPI1S_SPRF);//as soon as data is available in rx reg, read it.
*(p_rd_data++) = SPI1D;
gpio_set(XPIN_12,TRUE);//chip select high
I stand corrected. Apparently it does support it.