This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DUMMY SPI READ

Other Parts Discussed in Thread: CC2500, CC2550, CC1101

Hi all,

I'm using the PIC32MX360F512L to control the CC2500 trasceiver through the SPI interface (in 8bit mode).

To read a single CC2550 register I need to send a header byte containing the R/W bit set to 1, the burst bit to 0 (single read) and the register address.    Once this header byte is sent, the next 8 clock pulses will make me receive on the MISO pin the register value requested in the header.

However to successfully read the register content I need to perform this operation TWICE in a row, otherwise I read back a 15 (in decimal, meaning it's all 1).
Does anyone know why I have to make a dummy read first in order to get the proper value? 

Same thing happens when I try to send a strobe command, in order to send it I need to send it twice.
I think I'm making a logical or TIMING mistake somewhere in my read function but I can't figure out what's wrong..

My read function is:

BYTE readRegister(BYTE registro){
BYTE value, mask,mask1;


//the register value has to be padded with the mask +10000000 (READ MODE and SINGLE ACCESS)
//the mask 10000000 in hex is 0x80
mask = 0x80;  //this mask is used in the OR, it always adds the 1 for the reading 10000000
mask1 = 0xBF; //this mask is used to ensure the burst bit is always set to zero AND10111111 = 0xBF
value = 0;
CSlow();      //this enables the CC2500 trasceiver
while(!CCready());   //when the CC2500 is ready to communicate it puts MISO low and the function goes on

SPI1BUF = ((registro | mask) & mask1);  //this sends the header with the register that i want to read
while(!SpiChnTxBuffEmpty(1)); //exits when the transmit buffer is empty
SPI1BUF = 0x00;  //this sends a 0x00 just to make the clock toggle in order to read
while(!SpiChnTxBuffEmpty(1)); //exits when the transmit buffer is empty
value = SPI1BUF;  // THIS SHOULD BE THE CORRECT RESULT BUT IF I RETURN THE VALUE AT THIS POINT I GET A 0 RESULT.. why??? :o

//here i do everythig again to workaround the problem, and the result at the end is correct..
SPI1BUF = ((registro | mask) & mask1);
while(!SpiChnTxBuffEmpty(1));
SPI1BUF=0x00;
while(!SpiChnTxBuffEmpty(1));
value = SPI1BUF; //now I get the correct result..
//In this way the read function works..
return value;
CShigh();
}


thanks in advance

  • Hi Flavio.

    Try with the following:

    BYTE readRegister(BYTE registro){
    BYTE value, mask,mask1;

    mask = 0x80;  //this mask is used in the OR, it always adds the 1 for the reading 10000000
    mask1 = 0xBF; //this mask is used to ensure the burst bit is always set to zero AND10111111 = 0xBF
    value = 0;
    CSlow();      //this enables the CC2500 trasceiver
    SPI1BUF = ((registro | mask) & mask1);  //this sends the header with the register that i want to read
    while(!SpiChnTxBuffEmpty(1)); //exits when the transmit buffer is empty
    SPI1BUF = 0x00;  //this sends a 0x00 just to make the clock toggle in order to read
    while(!SpiChnTxBuffEmpty(1)); //exits when the transmit buffer is empty
    value = SPI1BUF;  // THIS SHOULD BE THE CORRECT RESULT BUT IF I RETURN THE VALUE AT THIS POINT I GET A 0 RESULT.. why??? :o
    CShigh();

    return value;

    }

    Ciao.

    Bruno B.

  • Hi thanks for your reply,

    that's exactly the problem. What you are suggesting is the first read and that reads back a 15 -only the first time. It works fine afterwards..

    That's why I'm using the workaround of two consecutive reads to get the proper value. But this creates me troubles when writing the code to send packets..

    Does anyone know why this is happening?

  • Hi Flavio,

    When you want to access a register from SPI the first thing you do is send the register address and operation that you want to execute (read/write).
    After that you need to either read the actual register value or write the value you want to send to that register.
    For a read you need to pulse the SPI clock which is generally achieved by sending a NOP command on the SPI port.
    For a write you simply place the value on the SPI interface.

    For command strobes you only need to give the register address and the write bit set to trigger that command, effectlively only transfering one byte on the SPI.

    So you effectively need two distinct functions one for general read/write operations and one for command strobes.

  • Hey pal,

    thanks for your reply.

    Yes I am aware of that procedure and my point is that strictly following that sequence to read a register I get a 15 as a result (the first time that's launched).

    Is there anything wrong with my read register function?

    Can you explain why?

  • From what I can see in your code I would suggest that you do a read following the first write (after you sent the register address).

    What might be happening (I don't know the CC2500) is that when you are clocking in the register address the chip is outputing a value from a previous command.
    I have a similar issue on the CC1101 where I simply ignore the first byte that th chip returns.

    Hope this helps,

    JM

  • Hey mate,

    thanks for your reply.

    I followed your advice and now the function works! :) I'm really grateful cos now I don't need to do the dummy read in order to get the proper value.. thanks a lot!

    The working function is:

    putcSPI1((registro | mask) & mask1);
    while(!SpiChnDataRdy(1));
    value = SPI1BUF;
    putcSPI1(0x00);
    while(!SpiChnDataRdy(1));
    value = SPI1BUF;

     Apparently not reading the status byte after the first write was causing him problems.. I guess.

    have a nice day

    cheers

     

  • From a hardware view SPI is two FIFOs in series, in a loop. One in the master and one in the slave.

    When you write to the master it serially clocks the data into the slave and  the slave data out of the slave back to the master.

    This is one continous operation, the master pushes the data out of the slave back to the master where it is read. You can not "read" the slave, you can only write to it and read what you get back. This is a subtle but important point. In your initial code you were pushing "pre-read" data (0xFF) back from the slave.

    Hope this helps.

    HMS