LockedSPI dummy read

Author
Flavio
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2009/06/29 07:56:34
  • Location: 0
  • Status: offline
2009/07/03 08:01:59 (permalink)
0

SPI dummy read

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 get 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? 
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
post edited by Flavio - 2009/07/03 10:23:48
#1

10 Replies Related Threads

    Vivio
    Senior Member
    • Total Posts : 130
    • Reward points : 0
    • Joined: 2008/11/13 00:35:46
    • Location: Romania
    • Status: offline
    RE: SPI dummy read 2009/07/03 21:06:35 (permalink)
    0
    There was an answer about a similar problem here on the forum if I remember correctly. Search a little more, I haven't fount it yet, but I know it's here.

    It's nice to be important, but it's more important to be nice!
    #2
    jtemples
    Super Member
    • Total Posts : 10144
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    RE: SPI dummy read 2009/07/04 14:13:13 (permalink)
    0
    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.

    And where do the next 8 clock pulses come from? Only the master can generate clock pulses, so the master must do another "dummy" write to do this.

    to successfully read the register content I need to perform this operation TWICE in a row

    I don't know anything about that chip, but you probably don't need to repeat the read command. Typically, the master just writes an FF or some other fixed dummy value to generate the necessary clocks to read the slave.
    #3
    Flavio
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2009/06/29 07:56:34
    • Location: 0
    • Status: offline
    RE: SPI dummy read 2009/07/05 04:34:21 (permalink)
    0
    Hey there
     
    thanks for your replies.
    I had a look in the forum but still can't find that post you are talking about, what do you recall from it?
     
    ps: sei Italiano??
    #4
    Vivio
    Senior Member
    • Total Posts : 130
    • Reward points : 0
    • Joined: 2008/11/13 00:35:46
    • Location: Romania
    • Status: offline
    RE: SPI dummy read 2009/07/05 05:24:13 (permalink)
    0
    I'm new in this stuff also. I have some SPI devices that I need to control. Few weeks ago I've looked for more info regarding SPI and in mchip forum there were some small examples for basic read/write operation. I haven't tried anything regarding SPI
    You can try to look at documentation regarding PERIPHERIAL LIBRARY and the one for the PIC32 family.

    Also look for this book:
    Programming 32-bit Microcontrollers in C Exploring the PIC32, by Di Jasio


    PS.: No, I'm from Romania.

    It's nice to be important, but it's more important to be nice!
    #5
    Rich T
    Junior Member
    • Total Posts : 93
    • Reward points : 0
    • Joined: 2008/12/28 06:19:09
    • Location: Boulder, Colorado, USA
    • Status: offline
    RE: SPI dummy read 2009/07/05 23:01:32 (permalink)
    0
    Hi,

    If you want to control your SPI interface interactively to understand how your peripherals work, you can actually load StickOS (from http://www.cpustick.com/downloads.htm -- documentation is there, too) onto your PIC32MX3F512L and then just log in from a terminal emulator on UART 1 using 9600 baud, 8 data bits, no parity, and then you can just control the chip selects and SPI port with a script, like (this example if from a Freescale MCU communicating with a serial flash device, but the PIC32 is basically the same, with different pin names):

    > list
    10 dim nrsti as pin scl for digital output
    20 dim ncs as pin qspi_cs0 for digital output
    30 dim cmd as byte, status as byte
    40 rem pulse rsti* low with cs*
    50 let ncs = 0, nrsti = 0, nrsti = 1
    60 sleep 100 ms
    70 let ncs = 1
    80 rem send write enable command
    90 let cmd = 0x6
    100 let ncs = 0
    110 qspi cmd
    120 let ncs = 1
    130 rem send read status register command
    140 let cmd = 0x5
    150 let ncs = 0
    160 qspi cmd, status
    170 let ncs = 1
    180 print hex status
    end
    > run
    0x2
    > _

    That's basically how I first hooked up a bunch of different SPI peripherals, including an SD flash card -- the interactive nature of it makes it pretty easy.

    -- Rich

    Embedded Systems Made Easy: http://www.cpustick.com/
    #6
    Flavio
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2009/06/29 07:56:34
    • Location: 0
    • Status: offline
    RE: SPI dummy read 2009/07/06 06:39:38 (permalink)
    0
    Any suggestions?? I'm really lost cos this 'double read' clashes with the rest of the code..
    #7
    Rich T
    Junior Member
    • Total Posts : 93
    • Reward points : 0
    • Joined: 2008/12/28 06:19:09
    • Location: Boulder, Colorado, USA
    • Status: offline
    RE: SPI dummy read 2009/07/06 08:09:13 (permalink)
    0
    I think you want to call "SpiChnDataRdy()", rather than "SpiChnTxBuffEmpty()" so that you know the receiver is ready before reading SPI1BUF.

    The receiver is ready a half clock after the transmitter is empty, I believe.

    If you want to see all of my SPI code for comparison, it is in sources/qspi.c (for a dozen different MCUs -- just search for PIC32) in the skeleton.zip archive at the bottom of this page:

    http://www.cpustick.com/downloads.htm

    The function you are interested in is qspi_transfer().

    -- Rich

    Embedded Systems Made Easy: http://www.cpustick.com/
    #8
    Rich T
    Junior Member
    • Total Posts : 93
    • Reward points : 0
    • Joined: 2008/12/28 06:19:09
    • Location: Boulder, Colorado, USA
    • Status: offline
    RE: SPI dummy read 2009/07/06 08:15:24 (permalink)
    0
    PS and if you can get a scope on the data in/out pins, that would be ideal to see what is going on!

    Different peripheral chips want in and out data clocked on different edges -- it can be very tricky.

    You have to get the CKE and CKP bits set correctly (for the peripheral chip you are talking to) in SPI1CON or things are just flakey.

    -- Rich

    Embedded Systems Made Easy: http://www.cpustick.com/
    #9
    Rich T
    Junior Member
    • Total Posts : 93
    • Reward points : 0
    • Joined: 2008/12/28 06:19:09
    • Location: Boulder, Colorado, USA
    • Status: offline
    RE: SPI dummy read 2009/07/06 08:17:34 (permalink)
    0
    And double-check the SMP bit as well...

    Embedded Systems Made Easy: http://www.cpustick.com/
    #10
    Flavio
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2009/06/29 07:56:34
    • Location: 0
    • Status: offline
    RE: SPI dummy read 2009/07/06 16:19:35 (permalink)
    0
    hey mate,
     
    thanks a lot for your replies.. with your advices I was able to fix this annoying problem! :)
     
    the working read register function is:
    putcSPI1((registro | mask) & mask1);
    while(!SpiChnDataRdy(1));
    value = SPI1BUF;
    putcSPI1(0x00);
    while(!SpiChnDataRdy(1));
    value = SPI1BUF;
     
    It was vital to implement your advices, I'm really greatful!!
     
    cheers
    #11
    Jump to:
    © 2017 APG vNext Commercial Version 4.5