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.

ADIS16480 Register values are getting swapped while reading using SPI

We are using LM4FH5qd microcontroller  from Tiva series,We are
using SPI protocol to read the register values from ADIS16480 sensor.When we
were reading single register we are getting proper value But when
we read more than one register then the values in the read
variables are getting swapped.Please see the code snippet below.

Are we reading properly or is there anything we are missing?

SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);
    InitConsole();
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
   
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);
   
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
                       SSI_MODE_MASTER, 1000000, 16);

    variable= SysCtlClockGet();

    SSIEnable(SSI0_BASE);

                              SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
                              SSIDataPut(SSI0_BASE, 0x6A00);//reading from 6A register
                              SSIDataGet(SSI0_BASE,&DataRx7[0]);
                              data_roll=(int)DataRx7[0];

                              SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
                              SSIDataPut(SSI0_BASE, 0x6C00);//reading from 6C register
                              SSIDataGet(SSI0_BASE,&DataRx8[0]);
                              data_pitch=DataRx8[0];

//Note:the problem is data_roll is having the value of the register 6C and data_pitch is having the value of the register 6A.

  • Hello John,

    For every SSIDataPut operation you would need to do a SSIDataGet. When sending the First SSIDataPut, Flush the RXFIFO by reading the data to a dummy word

    SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
    SSIDataGet(SSI0_BASE,&Dummy[0]);

    SSIDataPut(SSI0_BASE, 0x6A00);//reading from 6A register SSIDataGet(SSI0_BASE,&DataRx7[0]);

    Regards

    Amit

  • Thanks Amit for your quick reply. i have tried your suggestion by reading the data to a dummy.

    I actually need to read so many registers(most probably 5 or 6).

    when i tried to read 2 registers with the following code,still swapping was happening.

    SSIDataPut(SSI0_BASE,0x8000);  // for accessing pageID 0
    SSIDataGet(SSI0_BASE,&Dummy2[0]);
    SSIDataPut(SSI0_BASE, 0x6A00);
    SSIDataGet(SSI0_BASE,&DataRx7[0]);


    SSIDataPut(SSI0_BASE,0x8000);  // for accessing pageID 0
    SSIDataGet(SSI0_BASE,&Dummy3[0]);
    SSIDataPut(SSI0_BASE, 0x6C00);
    SSIDataGet(SSI0_BASE,&DataRx8[0]);

    But when i tried to read 3 registers with the following code i was able to read three register values properly

    SSIDataPut(SSI0_BASE,0x8000);  // for accessing pageID 0
    //SSIDataGet(SSI0_BASE,&Dummy2[0]);
    SSIDataPut(SSI0_BASE, 0x6A00);
    while(SSIBusy(SSI0_BASE)){}
    SSIDataGet(SSI0_BASE,&DataRx7[0]);


    SSIDataPut(SSI0_BASE,0x8000);  // for accessing pageID 0
    //SSIDataGet(SSI0_BASE,&Dummy3[0]);
    SSIDataPut(SSI0_BASE, 0x6C00);
    while(SSIBusy(SSI0_BASE)){}
    SSIDataGet(SSI0_BASE,&DataRx8[0]);

    SSIDataPut(SSI0_BASE,0x8000);  // for accessing pageID 0
    SSIDataGet(SSI0_BASE,&Dummy4[0]);
    SSIDataPut(SSI0_BASE, 0x6E00);
    while(SSIBusy(SSI0_BASE)){}
    SSIDataGet(SSI0_BASE,&DataRx9[0]);


    and again when i tried to read 4 registers it was not working.

    and FYI without reading the data into dummy i was able to read 2 registers and 4 registers properly but not 3 registers.

    i am not understanding what this peculiar behaviour of SPI.

    I am looking forward for your response.

    Thanks in advance

  • Hello John,

    Did you try resetting the SSI Peripheral, before enabling it. What I am suggesting is

    SysCtlPeripheralDisable(SYSCTL_PERIPH_SSI0);

    SysCtlPeripheralReset(SYSCTL_PERIPH_SSI0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    Regards

    Amit

  • Hello Amit,

    i did not do disabling and resetting, i did only

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    actually my working setup is away from my sitting place,that is why i am unable to check immediately,any how i'll try this and come to you.

    is it mandatory to disable and reset everytime?

  • Hello John,

    It is preferred to do it this way when developing. What happens when a debugger starts depends upon the understanding of the debugger on the user end. Like in CCS a CPU Reset will restart just the CPU and not reset the peripherals. On the other hand a System Reset to restart will cause the whole device to be reset.

    When a peripheral is doing an operation and CPU is reset, stale status may remain causing data/control to misbehave at times.

    Regards

    Amit

  • Hello Amit,

    i got your point.but when i tried those statements like below no output was coming

    SysCtlPeripheralDisable(SYSCTL_PERIPH_SSI0);

    SysCtlPeripheralReset(SYSCTL_PERIPH_SSI0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    but without Reset if i do only Disable and Enable the code is working but with no improvement,i.e still my variables are having swapped values.

  • Hi,

    John, it is not clear how did you declared the DataRx_ [] variables and what is really swapped - either the received data from SPI, either your variables processed further. Take into account this micro is little endian.

    Can you specify?

    Petrei

  • Hello Amit,

    here i am adding how they are declared and the portion of the code which was causing the swapping,please go through the following snippet.

    declarations:
    
    unsigned long DataRx7[1];
    unsigned long DataRx8[1];  
    
    
     SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
        InitConsole();
        SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
       
        GPIOPinConfigure(GPIO_PA2_SSI0CLK);
        GPIOPinConfigure(GPIO_PA3_SSI0FSS);
        GPIOPinConfigure(GPIO_PA4_SSI0RX);
        GPIOPinConfigure(GPIO_PA5_SSI0TX);
        
        GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                       GPIO_PIN_2);
       
        SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,
                           SSI_MODE_MASTER, 1000000, 16);
    
        variable= SysCtlClockGet();
    
        SSIEnable(SSI0_BASE);
    
                                  SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
                                  SSIDataPut(SSI0_BASE, 0x6A00);//reading from 6A register
                                  SSIDataGet(SSI0_BASE,&DataRx7[0]);
                                  data_roll=(int)DataRx7[0];
    
                                  SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
                                  SSIDataPut(SSI0_BASE, 0x6C00);//reading from 6C register
                                  SSIDataGet(SSI0_BASE,&DataRx8[0]);
                                  data_pitch=DataRx8[0];
    
    //Note:the problem is data_roll is having the value of the register 6C and data_pitch is having the value of the register 6A.
    

  • Hi,

    Roll and pitch are 16-bit or 32-bit data? if 32 bit, you need an extra, dummy SSIDataPut, and to collect 32 bits an extra SSIDataGet read.

    Not reading 32 bits explain the finding of roll instead of pitch.

    Petrei

  • Hello Petrei,

    Roll and Pitch are 16-bit data according to our (ADIS16480) sensor data sheet.

    what else could be the problem.

  • Hi,

    Apparently could be 16 bits, but could be also some data sheet omission. You can check by yourself this way: set a breakpoint on line 34 in the last snippet code posted and go to SPI registers and examine the SPI data register - if you find out there the roll info, for sure the data is 32 bits. 

    You can also add a third parameter to read and see if the pitch moves to that one and the new one should be found on roll data. This is for sure the indication the data is 32 bits and must be treated as is.

    Petrei

  • Hello Petrei,

    I did not get your point clearly,but in a mean while i tried reading the register and writing its value to the local buffer as below,it is working now with any number of registers(earlier few techniques were good either for even no.of registers or for odd no.of registers)

                              

                                  SSIDataPut(SSI0_BASE,0x8000);// for accessing pageID 0
                                  SSIDataGet(SSI0_BASE,&Dummy[0]);
    			      
                                  SSIDataPut(SSI0_BASE, 0x6A00);//reading from 6A register
                                  SSIDataGet(SSI0_BASE,&DataRx7[0]);
                                  SSIDataPut(SSI0_BASE, 0x6A00);//reading from 6A register
                                  SSIDataGet(SSI0_BASE,&DataRx7[0]);
                                  data_roll=(int)DataRx7[0];
    
                                  
    			      SSIDataPut(SSI0_BASE, 0x6C00);//reading from 6C register
                                  SSIDataGet(SSI0_BASE,&DataRx8[0]);
                                  SSIDataPut(SSI0_BASE, 0x6C00);//reading from 6C register
                                  SSIDataGet(SSI0_BASE,&DataRx8[0]);
                                  data_pitch=(int)DataRx8[0];
    
     
    

    after this data_roll is having the value read from register 6A and data_pitch is having the value read from register 6C.
    what could be the logic behind this solution,can you explain?


  • Hi,

    You did what I suggested in one of my previous posts - added an extra (dummy) word to get the data. This is anyway also shown in data sheet for output data - should be three words transmitted and only the lasts two carries the data. For you the third word was received in the next command, so read in other parameter. I expected you to really use the debugger and set breakpoints to verify when really data shows up.

    In other words, your chip always send 32 bits, the upper 16 are dummy for data declared as 16 bits.

    Now you can move further to organize your routines for the rest of the application.

    Petrei