• AVR Freaks

Hot!Strange SPI behaviour

Author
elberto
Super Member
  • Total Posts : 510
  • Reward points : 0
  • Joined: 2005/05/18 06:35:17
  • Status: offline
2020/06/02 14:39:13 (permalink)
0

Strange SPI behaviour

Hi to all users!
I'm using dsPIC33EP512GM304 and I try to read sensor through SPI interface (atached image).

Taking a look to datasheet (DS70005185A reference manual) I set interface for clock mode (CKP=1, CKE = 0).

Here my SPI settings:

    SPI2CON1bits.DISSCK = 0; // pin assegnato a SCK 
    SPI2CON1bits.DISSDO = 0; // pin assegnato a SDO
    SPI2CON1bits.MODE16 = 0; // lavoro a 8 bit
    SPI2CON1bits.MSTEN = 1; // attivo la modalità master
    SPI2CON1bits.SMP = 0; // campionamento a metà del bit
   SPI2CON1bits.CKP = 1; // dovrebbe essere quello corretto
    SPI2CON1bits.CKE = 0;

    // utilizzata per LIS3DSH per test
 
    SPI2CON1bits.PPRE = 0; // prescaler primario 1:64
    SPI2CON1bits.SPRE = 0; // prescaler secondario 1:8
    SPI2STATbits.SPIEN = 1; // attivo il modulo SPI



Then I read sensor:

 unsigned char MyDummy;
 MEMS_CS = 0;
 //Delay10us(1);
    __delay_us(10);
    MyDummy = SPI2BUF; // dummy read
    SPI2STATbits.SPIROV = 0; // resetto eventuale flag di overflow
    //IFS2bits.SPI2IF = 0; // resetto il flag
 SPI2BUF = Indirizzo | 0b10000000; // Write data to be transmitted (0 = scrittura, 1 = lettura)
    while(SPI2STATbits.SPITBF); // wait for TX buffer empty
    while(!SPI2STATbits.SPIRBF); // wait for RX buffer full
    MyDummy = SPI2BUF; // dummy read
    SPI2BUF = 0x00; // dummy write
    while(SPI2STATbits.SPITBF); // wait for TX buffer empty
    while(!SPI2STATbits.SPIRBF); // wait for RX buffer full
    MyDummy = SPI2BUF; // effettuo una lettura dummy per evitare l'overflow
 //__delay_us(10);
 MEMS_CS = 1;



Then I get additional clock pulse as attached image.
Why? I can't understand....
Thanks.




Attached Image(s)

#1

11 Replies Related Threads

    ric
    Super Member
    • Total Posts : 28024
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Strange SPI behaviour 2020/06/02 14:46:23 (permalink)
    0
    I see one clock pulse, then 8, then 7.
    So, you are getting 16 pulses, but I cannot explain the odd spacing.
     
    n.b. I don't think you need the waits for SPITBF, just on SPIRBF is enough.
     
    What value was in "Indirizzo" when you called this function?
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    du00000001
    Just Some Member
    • Total Posts : 3858
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Strange SPI behaviour 2020/06/02 16:45:51 (permalink)
    0
    See the errata sheet - issue 38.
    Looks like you ran exactly into this  :(
    Remedy: see the errata sheet.
     
    P.S.: The CLK timing is really weird. But looks like the "shifted by 1 bit" might result exactly from this fancy SCK timing (resp. some mismatch between the clock generation and the register transfer).
    BASICALLY SPI clock patterns may exhibit any sort of non-uniformity unless they violate the max. frequency specifications and do not exhibit a significant loss of performance. But I wouldn't consider this behavior as "normal".

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #3
    elberto
    Super Member
    • Total Posts : 510
    • Reward points : 0
    • Joined: 2005/05/18 06:35:17
    • Status: offline
    Re: Strange SPI behaviour 2020/06/03 11:01:02 (permalink)
    0
    Thanks for help.
    On datasheet I find:
    • Set the Slave Select line to the Idle state
    • Set the SCKx pin high
    • Enable Master mode
    • Enable the module
    • Assert the Slave Select line

    But Slave Select is for SPI in salve mode, not my case. Or it means Chip Select instead?
    Or have I to set SSx pin someway?

    Set the SCKx pin high:
        // Set the SCKx pin high
        MEMS_SCK = 1;
        MEMS_SCK_TRIS = 0;

     
    Enable Master mode and enable the module
       // Enable Master mode
        SPI2CON1bits.MSTEN = 1; // attivo la modalità master
        
        // Enable the module
        SPI2STATbits.SPIEN = 1; // attivo il modulo SPI


    Assert the Slave Select line: even if working in master mode?

    My code is:


    Nop();
        Nop();
        Nop();
        // Set the Slave Select line to the Idle state
        MEMS_CS = 1; // linea CS in modalità idle
        
        // Set the SCKx pin high
        MEMS_SCK = 1;
        MEMS_SCK_TRIS = 0;
        
        // Enable Master mode
        SPI2CON1bits.MSTEN = 1; // attivo la modalità master
        
        // Enable the module
        SPI2STATbits.SPIEN = 1; // attivo il modulo SPI
        
        
        
        SPI2CON1bits.DISSCK = 0; // pin assegnato a SCK
        SPI2CON1bits.DISSDO = 0; // pin assegnato a SDO
        SPI2CON1bits.MODE16 = 0; // lavoro a 8 bit
        SPI2CON1bits.MSTEN = 1; // attivo la modalità master
        SPI2CON1bits.SMP = 0; // campionamento a metà del bit
        
        SPI2CON1bits.CKP = 1; // dovrebbe essere quello corretto, ma ho un impulso di clock in più.
        SPI2CON1bits.CKE = 0;

        // utilizzata per LIS3DSH per test
        // test per LIS3DSH, da tohliere
        SPI2CON1bits.PPRE = 0; // prescaler primario 1:64
        SPI2CON1bits.SPRE = 0; // prescaler secondario 1:8


    But no changes on waveforms during reading.

    BTW, "indirizzo" is set to 0x0F.







    #4
    du00000001
    Just Some Member
    • Total Posts : 3858
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Strange SPI behaviour 2020/06/03 18:24:21 (permalink)
    0
    You may read "slave select" and "chip select" as synonyms. That denomination just depends on the author's view. (While "chip select" is a general term, "slave select" is somehat SPI-specific - not depending on whether applied to master or slave. Master selects slave, slave is selected by master.)
     
    And yes (provided the slave has an SS input): deselect the SS to avoid the slave "listening" to the bus. IMHO, the errata sheet is very clear about this.
     
    And I do not really expect the waveforms to change. (That one seems to be "pure hardware".) It's more about preventing the potential bit shift issue.

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #5
    elberto
    Super Member
    • Total Posts : 510
    • Reward points : 0
    • Joined: 2005/05/18 06:35:17
    • Status: offline
    Re: Strange SPI behaviour 2020/06/19 14:43:08 (permalink)
    0
    Mmh... ok, rewritten code and updated XC16 compiler.
    I don't see strange signals but new issue reading multiple bytes:

    MEMS_CS = 0;

    SPI2BUF = OUT_X_L_addr | 0b10000000; // Write data to be transmitted (0 = scrittura, 1 = lettura)
    IFS2bits.SPI2IF = 0;    // reset flag SPIRBF    
    Dummy_uchar = SPI2BUF; // dummy read for SPIRBF reset
    while(!SPI2STATbits.SPIRBF); // wait for RX buffer
                
    for (i = 0; i<6; i++)
    {
                IFS2bits.SPI2IF = 0; // reset flag SPIRBF
                SPI2BUF = 0; // dummy write to clear flag
                Dummy_uchar = SPI2BUF; // dummy read per resettare flag SPIRBF
                while(!SPI2STATbits.SPIRBF); // wait for RX buffer full
                MEMS_RegArray[i] = SPI2BUF; // read byte
            }
            
          
            MEMS_CS = 1;

    It works for a while, suddenly it hangs usually at first  while(!SPI2STATbits.SPIRBF).
    I can see first byte has sent (8 clock pulses), then nothing.
    I can't understand why SPIRBF and SPI2IF both low.
    Maybe other bug?
    #6
    ric
    Super Member
    • Total Posts : 28024
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Strange SPI behaviour 2020/06/19 14:52:47 (permalink)
    0
    elberto
    It works for a while, suddenly it hangs usually at first  while(!SPI2STATbits.SPIRBF).
    I can see first byte has sent (8 clock pulses), then nothing.
    I can't understand why SPIRBF and SPI2IF both low.
    Maybe other bug?

    that looks like a bug in your code.
    These lines are out of order:
    SPI2BUF = OUT_X_L_addr | 0b10000000; // Write data to be transmitted (0 = scrittura, 1 = lettura) 
    IFS2bits.SPI2IF = 0;    // reset flag SPIRBF    
    Dummy_uchar = SPI2BUF; // dummy read for SPIRBF reset
    while(!SPI2STATbits.SPIRBF); // wait for RX buffer

    should be
    IFS2bits.SPI2IF = 0;    // reset flag SPIRBF    
    Dummy_uchar = SPI2BUF; // dummy read for SPIRBF reset
    SPI2BUF = OUT_X_L_addr | 0b10000000; // Write data to be transmitted (0 = scrittura, 1 = lettura)
    while(!SPI2STATbits.SPIRBF); // wait for RX buffer



     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    T Yorky
    Super (Thick) Member
    • Total Posts : 560
    • Reward points : 0
    • Joined: 2012/08/28 02:07:35
    • Location: UK
    • Status: offline
    Re: Strange SPI behaviour 2020/06/20 13:04:08 (permalink)
    0
    elberto, your method of servicing the SPI is a bit weird. Can you confirm if this is the whole program, or is it just an extract?
    What else is in the program? Is there other tasks? Other interrupt routines, timers for example?
    #8
    T Yorky
    Super (Thick) Member
    • Total Posts : 560
    • Reward points : 0
    • Joined: 2012/08/28 02:07:35
    • Location: UK
    • Status: offline
    Re: Strange SPI behaviour 2020/06/26 10:10:32 (permalink)
    3 (1)
    As of Friday no response by OP. So for any others that may have found this thread. Explanation..
    The legacy SPI port operating as a master is nothing more than a 'gearbox'. When a byte is sent out (Tx) a byte is brought in (Rx). The master is in total control of this mechanism. If the master has not sent out a byte. There is no reason to clear a byte from the Rx buffer. Even if the Rx signal has had various 1's and 0's on the pin. Nothing will be clocked in. In addition when the master sends a byte (Tx), the operation is totally predictable. It will take a specific number of clock cycles depending on the divisors (Primary/secondary) and so the time to send this byte is fixed (see allowance described later). Unless the master sends a byte (Tx) and never reads the Rx buffer, there can never be an overflow on the receiver. In addition the Interrupt Flag is set on receiving a byte so can be monitored instead of SPIRBF. The IF is the better choice. Simple sequence is: Reset IF. Send Byte (Tx). Wait IF. Read Byte(Rx). There is nothing more! Providing it is configured correctly. You do not read after sending and then wait (as in above code). Always read a byte in the sequence described, after sending a byte.
    After reading a byte the next byte can be sent. But note here, the transmission may not start immediately, the clock divisors create the SPI clock. If the divisors are large, then the next full SPI clock is when the next byte starts. So if there is a processing delay the period for the next byte may be up to 9 clocks. One lost and then 8 data clocks.
    For word operation, read word above instead of byte.
    Hope this assists.
    T Yorky.
    post edited by T Yorky - 2020/06/26 10:12:29
    #9
    elberto
    Super Member
    • Total Posts : 510
    • Reward points : 0
    • Joined: 2005/05/18 06:35:17
    • Status: offline
    Re: Strange SPI behaviour 2020/06/27 05:33:54 (permalink)
    0
    T Yorky
    elberto, your method of servicing the SPI is a bit weird. Can you confirm if this is the whole program, or is it just an extract?
    What else is in the program? Is there other tasks? Other interrupt routines, timers for example?


    Sorry, I'm out of office in this period, I'll back Monday.
    I changed SPI code and now I'm waiting: program usually works correctly up to four days so I'm still evaluating changes....

    This is not all code: in few words I'm writing firmware for datalogger.
    I get sync pulse (PPS) from GPS receiver and secondary sync pulse (PPS) from RTC when GPS is off.
    I sync internal time (TMR1, interrupt every millisecond) to lock to sync pulses (GPS or RTC).
    Meanwhile I'm reading sensor (400 or 500 samples per second), filtering values and filling buffer with samples read every 10ms.
    Filled buffer with 20 samples (with timestamp) I send data out from serial port.
    Once I got timing working correctly (and sending fake data) I started collecting data from sensor.
    If not reading data (just using INT2 to create random values) it worked correctly for several weeks.
    Then I started to read data using SPI.
    Initially I set interrupt priority for INT2 (interrupt for sensor data ready) higher than U2TX interrupt: transmission was not working because sometimes I write into U2TXREG but U2TXIF still low after byte has been sent.
    So I increased interrupt priority for U2TX (higher than INT2) and SPI reading hangs on while(!SPI2STATbits.SPIRBF), transmission of serial data working correctly.


    #10
    elberto
    Super Member
    • Total Posts : 510
    • Reward points : 0
    • Joined: 2005/05/18 06:35:17
    • Status: offline
    Re: Strange SPI behaviour 2020/06/27 06:29:23 (permalink)
    0
    T Yorky
    [...] Simple sequence is: Reset IF. Send Byte (Tx). Wait IF. Read Byte(Rx). There is nothing more! Providing it is configured correctly. You do not read after sending and then wait (as in above code). Always read a byte in the sequence described, after sending a byte.
    [...]



    My code (wrong):

    SPI2BUF = OUT_X_L_addr; // Write data to be transmitted (it will take some time...)
    IFS2bits.SPI2IF = 0; // reset flag SPIRBF (don't take care about this, I don't use SPI2IF on this example)
    Dummy_uchar = SPI2BUF; // during transmission I clear SPIRBF flag with dummy read of SPI2BUF, here transmission should be still in progress....
    while(!SPI2STATbits.SPIRBF); // wait transmission end polling SPIRBF flag


    Ric code (it should work, I hope :D ):



    IFS2bits.SPI2IF = 0; // reset flag SPIRBF (don't take care about this, I don't use SPI2IF on this example)

    Dummy_uchar = SPI2BUF; // I clear SPIRBF flag with dummy read of SPI2BUF, here transmission hasn't still started...

    SPI2BUF = OUT_X_L_addr; // Write data to be transmitted, transmission should start here....
    while(!SPI2STATbits.SPIRBF); // wait transmission end polling SPIRBF flag



    On dsPIC33EP512GP304 datasheet it's reported to check DS70005185 for SPI, taking a look to DS70005185A (Figure 3-2, page 16):



    IFS2bits.SPI2IF = 0; // reset flag SPIRBF (don't take care about this, I don't use SPI2IF on this example)

    SPI2BUF = OUT_X_L_addr; // Write data to be transmitted (it will take some time...)
    // now transmission starts, it will take some time....
    Dummy_uchar = SPI2BUF; // here transmission should be still in progress, I clear SPIRBF flag with dummy read of SPI2BUF
    while(!SPI2STATbits.SPIRBF); // wait transmission end polling SPIRBF flag



    Is it misleading or am I wrong?
    post edited by elberto - 2020/06/27 06:33:19
    #11
    T Yorky
    Super (Thick) Member
    • Total Posts : 560
    • Reward points : 0
    • Joined: 2012/08/28 02:07:35
    • Location: UK
    • Status: offline
    Re: Strange SPI behaviour 2020/06/27 08:12:47 (permalink)
    0
    It is what I suspected. Your interrupt is causing the issue. But the interrupt is not the problem. It is your weird way of servicing the SPI. Not sure where you have got this silly method from. But take a bit of advice, follow what I have written.
    So you understand what is happening. You have set up a totally statistical software bug that is dependent on how hard you work the SPI and the rate of interrupts and the length of time in those interrupt routines.
    You write, you read (dummy?) then wait, then read. The interrupt is occurring between your write and your read (dummy). this takes time. The SPI sends and receives a byte. Int returns. You read (dump?) then expect a byte to arrive. Lock up.
    Apply for a job at Microsoft?
    No dummy read sh1t. It is some sort of witchcraft nonsense read on the internet somewhere !!!
    #12
    Jump to:
    © 2020 APG vNext Commercial Version 4.5