• AVR Freaks

Answereddspic33e SPI no clock

Page: 12 > Showing page 1 of 2
Author
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
2014/11/12 13:59:49 (permalink)
0

dspic33e SPI no clock

Hello, 
 
I have 2 dsPIC33E256MU806's on my circuit and they are connected over SPI. The master is using SPI2 (hardware), slave is using SPI1 configured through PPS.
 
I am running them both at 70mips and both clocks work ok -  UART with DMA is successfully working on the slave. I have been trying to get SPI working but I cant even get clock signal (checked with a logic analyzer). Below is the last code for master and slave I've tried. Debugging with Pickit3 on master doesnt work (gives an error saying to check clock or PGD/PGC..), but it does debug on slave. I am beginning to think I might have damaged the master during soldering (it is a 64pin QFN package - I had a really hard time with it, slave was done in one shot). I did check the lines as best as I could and there seems to be no short circuits or broken lines. Any advice would greatly be appreciated. Thanks
 
Master main

#include <xc.h>
...
#include <spi.h>
...
#include "SPI.h"
...

_FOSCSEL(FNOSC_PRIPLL); // Primary Oscillator (XT, HS, EC) with PLL
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_HS); // Enable Clock Switching and Configure POSC in HS mode
_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software
_FGS(GWRP_OFF); // General segment Write protect turned off
_FICD(JTAGEN_OFF & ICS_PGD1);
_FPOR(ALTI2C1_ON); // ASDA1/ASCK1 pins are selected as the I/O pins for I2C1

int main(void) {
    // Configure Oscillator to operate the device at 140Mhz
    // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
    // Fosc= 16M*35/(2*2)=140Mhz for 16M input clock
    PLLFBD = 33; // M=35
    CLKDIVbits.PLLPOST = 0; // N1=2
    CLKDIVbits.PLLPRE = 0; // N2=2

    __builtin_write_OSCCONH(0x03);
    __builtin_write_OSCCONL(0x01);

    while (OSCCONbits.COSC != 0b011); // Wait for Clock switch to occur
    while (OSCCONbits.LOCK != 1) {}; // Wait for PLL to lock

    RCONbits.SWDTEN = 0; // Disable Watch Dog Timer
    PMD1 = 0xF7CF; // SPI2 / UART1 / Timer1
    PMD2 = 0xFFFF;
    PMD3 = 0xFFFF;
    PMD4 = 0xFFFF;
    PMD5 = 0xFFFF;
    PMD6 = 0xFFFF;
    PMD7 = 0xC0; // DMA0-7 Enabled

    /************** P I N D E F I N I T I O N S ***************************/
    ANSELB = 0; // Make all the ANx pins as digital pins
    ANSELC = 0;
    ANSELD = 0;
    ANSELE = 0;
    CNENG = 0;

    _ANSE7 = 0;
    _ANSG6 = 0;
    _ANSG7 = 0;
    _ANSG8 = 0;

    CONT_LED_0_TRIS = 0; // OUTPUT
    CONT_LED_1_TRIS = 0;

    _TRISF4 = 0; // OUT_FN_PPS_U1TX
    _TRISB15 = 1; // IN_FN_PPS_U1RX

    _TRISE7 = 0; // SS2
    _TRISG6 = 0; // SCK2
    _TRISG7 = 1; // SDI2
    _TRISG8 = 0; // SDO2

    PPSUnLock;
    PPSInput ( IN_FN_PPS_U1RX, IN_PIN_PPS_RPI47); // UART
    PPSOutput ( OUT_FN_PPS_U1TX, OUT_PIN_PPS_RP100);
    PPSLock;
    /* end PIN DEFINITIONS ****************************************************/

// Init_UART();
    Init_Timer1();
// init_strapdown();
// init_I2c();
    Init_SPI( );

    CONT_LED_0_LAT = 0;
    CONT_LED_1_LAT = 0;
    OKtoSendData = 0;

    int k;
    k = 12;

    unsigned int RX_data;
    __delay_ms(250);

    LATEbits.LATE7 = 1; // SPI2 SS

    while (1) {

       if (OKtoSendData) { // <--- FROM TIMER1, TURNS ON EVERY 500ms
            CONT_LED_1_LAT = 1;
            LATEbits.LATE7 = 0; // SPI2 SS
            __delay_us(50);
            WriteSPI2(k);
            while(SPI2STATbits.SPITBF);

           RX_data = ReadSPI2();
            while(SPI2STATbits.SPIRBF);
            __delay_us(50);
            LATEbits.LATE7 = 1; // SPI2 SS

            CONT_LED_1_LAT = 0;
            OKtoSendData = 0;
        }
    } // END while
} // END main

 
Master SPI config

#include <spi.h>
#include "SPI.h" // <------- ONLY has function prototypes

void __attribute__((__interrupt__, no_auto_psv )) _SPI2Interrupt(void) {
    IFS2bits.SPI2IF = 0;
    CONT_LED_0_LAT ^= 1;
}

void Init_SPI() {
    unsigned int SPICONValue;
    unsigned int SPISTATValue;
    unsigned int SPIFRAMEValue;

    CloseSPI2();

    IFS2bits.SPI2IF = 0;
    ConfigIntSPI2(SPI_INT_PRI_3 & SPI_INT_EN);

    SPICONValue = ENABLE_SDO_PIN &
                        SPI_MODE16_ON &
                        SPI_SMP_OFF &
                        SPI_CKE_ON &
                        SLAVE_ENABLE_OFF &
                        CLK_POL_ACTIVE_HIGH &
                        MASTER_ENABLE_ON &
                        SEC_PRESCAL_7_1 &
                        PRI_PRESCAL_64_1;
    
    SPIFRAMEValue = FRAME_ENABLE_OFF;

    SPISTATValue = SPI_ENABLE &
                        SPI_IDLE_CON &
                        SPI_RX_OVFLOW_CLR;

    OpenSPI2(SPICONValue, SPIFRAMEValue, SPISTATValue );
}

 
 
Slave main (just posting the pin settings to keep it tidy, rest is the same)
I couldnt use pps functions to set the pins, these pins werent defined
main loop is just while(1) {}; Im not writing to master from slave
 

/************** P I N D E F I N I T I O N S ***************************/
    
    ANSELB = 0; // Make all the ANx pins as digital pins
    ANSELC = 0;
    ANSELD = 0;
    ANSELE = 0;
    CNENG = 0;

    _ANSC14 = 0;
    _ANSC13 = 0;

    _TRISF4 = 0; // OUT_FN_PPS_U1TX
    _TRISB15 = 1; // IN_FN_PPS_U1RX

    _TRISC13 = 1; // _SCK1
    _TRISD0 = 0; // _SD01
    _TRISD11 = 1; // _SDI1
    _TRISC14 = 1; // _SS1

    PPSUnLock;
        PPSInput (IN_FN_PPS_U1RX, IN_PIN_PPS_RPI47);
        PPSOutput (OUT_FN_PPS_U1TX, OUT_PIN_PPS_RP100);

        _SS1R = 62; // SPI1 Slave Select 
        _SCK1R = 61; // SPI1 Clock IN 
        _RP64R = 5; //  SPI1 Data Output
        _SDI1R = 75; // SDI1
    PPSLock;
    
    CONT_LED_0_TRIS = 0; // OUTPUT
    CONT_LED_1_TRIS = 0;

    /* end PIN DEFINITIONS ****************************************************/
 
 
Slave SPI

#include <spi.h>
#include "SPI.h"

void __attribute__((__interrupt__, no_auto_psv )) _SPI1Interrupt(void) {
    IFS0bits.SPI1IF = 0;
}

void Init_SPI() {
    unsigned int SPICONValue;
    unsigned int SPISTATValue;
    unsigned int SPIFRAMEValue;

    CloseSPI1();

    IFS0bits.SPI1IF = 0;
    ConfigIntSPI1(SPI_INT_PRI_3 & SPI_INT_EN);

    SPICONValue = ENABLE_SDO_PIN &
                        SPI_MODE16_ON &
                        SPI_SMP_OFF &
                        SPI_CKE_ON &
                        SLAVE_ENABLE_ON &
                        CLK_POL_ACTIVE_HIGH &
                        MASTER_ENABLE_OFF &
                        SEC_PRESCAL_7_1 &
                        PRI_PRESCAL_64_1;

    SPIFRAMEValue = FRAME_ENABLE_OFF;

    SPISTATValue = SPI_ENABLE &
                        SPI_IDLE_CON &
                        SPI_RX_OVFLOW_CLR;

    OpenSPI1(SPICONValue, SPIFRAMEValue, SPISTATValue );
}

 
Couldn't link the data sheet above;

#1
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/12 14:44:38 (permalink)
3 (1)
Ok, the first thing I notice is that on your master side you write to the SPI buffer and then wait for the TBF flag to clear.  You really only need to do this if you are planning on writing multiple bytes as fast as possible.  Even then, you need to check the Errata on your PIC as in my experience a SIGNIFICANT number of the dsPIC series suffer from a glitch with the SPIxTBF flag where it clears before the buffer is actually empty.  ... Or at least I believe that was the specifics of the glitch.... I know it was with the SPIxTBF flag though.  ANYWHO, if you're only sending one byte/word then you don't need to check that bit before proceeding.
 
The next thing is I notice that you are checking the SPIxRBF flag.  This is good, but you're doing it wrong.  This bit tells you when there is a byte/word to be read and should go before your attempt to read out the SPIxBUF.  And also, what you should be waiting for is the flag to be set, not be cleared.
 
So what you need is this:
            CONT_LED_1_LAT = 1;
            LATEbits.LATE7 = 0; // SPI2 SS
            __delay_us(50);
            WriteSPI2(k);
//            while(SPI2STATbits.SPITBF);    <~~~Don't need this

           while(!SPI2STATbits.SPIRBF);        // <~~~~~~ This needs to be before your read and
                                               //         you need to wait for the bit to be set, not cleared
           RX_data = ReadSPI2();
            __delay_us(50);
            LATEbits.LATE7 = 1; // SPI2 SS

            CONT_LED_1_LAT = 0;
            OKtoSendData = 0;

#2
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 00:20:17 (permalink)
0
Thank you for your input, I never thought to check the errata, there are two issues regarding SPI but both to do with framing. 
From the errata;
When using the frame sync pulse output feature (SPIxCON2 = 1) in Master Mode (SPIxCON2 = 0), the frame sync pulse is not being generated with an active low pulse (SPIxCON2 = 0). (Has a workaround)

When in SPI Slave mode (SPIxCON1 = 0) and using the frame sync pulse output feature (SPIxCON2 = 1) in Slave Mode (SPIxCON2 = 0), the Frame Sync Pulse Edge Select bit must be set to ‘0’ (SPIxCON2 = 0) (No workaround)

 
In the reference manual for SPI (DS70005185A) it is written that SCK needs to be set as input and output, I am curious if this still needs to be set if I use the dedicated hardware pins for SPI2.

3.1 Configuring the Port Pins
The SPIx module inputs must be configured as digital pins by setting the corresponding bits in the ADxPCFG registers,
or by clearing the bits in the ANSELx or ANSx registers with respect to a particular device. If the device has a
Peripheral Pin Select (PPS) feature, the SCKx pin must be mapped as both input and output in Master mode.

post edited by Dersu Uzala - 2014/11/13 00:25:15
#3
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 00:49:19 (permalink)
0
I changed the code as above and put two led indicators to each write and read sections. The code gets stuck at while(!SPI2STATbits.SPIRBF); CONT_LED_0_LAT never goeas low

I tried both while(SPI2STATbits.SPITBF); commented out and not - I am keeping it in the code so I dont forget to include it again later since I will be sending long data streams IF I get this working.

while (1) {
if (OKtoSendData) {

LATEbits.LATE7 = 0; // SPI2 SS
__delay_us(10);
CONT_LED_1_LAT = 1;
WriteSPI2(k);
while(SPI2STATbits.SPITBF);
CONT_LED_1_LAT = 0;


CONT_LED_0_LAT = 1;
while(!SPI2STATbits.SPIRBF);
RX_data = ReadSPI2();
CONT_LED_0_LAT = 0;
__delay_us(10);
LATEbits.LATE7 = 1; // SPI2 SS
OKtoSendData = 0;
}
}

#4
tmr_suresh
Senior Member
  • Total Posts : 105
  • Reward points : 0
  • Joined: 2012/09/13 04:00:07
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 01:10:02 (permalink)
0
which version of xc16 ?  I had some issues with pps.h in v1.11 . try using the latest compiler which has corrected pps.h
#5
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 02:20:01 (permalink)
0
I just updated XC16 to 1.23 and no change. I also updated MPLAB to 2.26 to upgrade the firmware on Pickit3, but I still cant debug the master dspic.
 
Also as per Susan's advice on another thread related to SPI 
Aussie Susan
Don't forget that you need to read any value received by the SPI peripheral before the next value is received (especially in the slave, generally not a problem for the master) otherwise you will get an overflow and the device will stop until it is cleared.
Can you check the SCK and SDI/SDO lines with a scope to see if they are reacting the way you expect?
Susan

 
I added the below code to slave,

while (1) {
CONT_LED_1_LAT = 1;
while(!DataRdySPI1());
datard = ReadSPI1();
CONT_LED_1_LAT = 0;
}

 
but it seems the slave doesnt receive since the led never goes low - which is not surprising since there is still no clock signal on the line. 
#6
tmr_suresh
Senior Member
  • Total Posts : 105
  • Reward points : 0
  • Joined: 2012/09/13 04:00:07
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 02:43:16 (permalink)
4 (1)
if there is no clock signal then chances are  input/output  pps  configuration .
please look the sample code below for spi3/spi4
 
 
 
PPSUnLock;

iPPSInput(IN_FN_PPS_SDI3 ,IN_PIN_PPS_RP124); //RG12 PIN 139 // SPI3
iPPSOutput(OUT_PIN_PPS_RP113,OUT_FN_PPS_SDO3); //RG1 PIN 128
iPPSOutput(OUT_PIN_PPS_RP112,OUT_FN_PPS_SCK3); //RG0 PIN 129

iPPSInput(IN_FN_PPS_SDI4 ,IN_PIN_PPS_RP108); //RF13 PIN 57 // SPI4
iPPSOutput(OUT_PIN_PPS_RP97,OUT_FN_PPS_SDO4); //RF1 PIN 97
iPPSOutput(OUT_PIN_PPS_RP96,OUT_FN_PPS_SCK4); //RF0 PIN 96

PPSLock;

 
 
 
#7
T Yorky
Super (Thick) Member
  • Total Posts : 522
  • Reward points : 0
  • Joined: 2012/08/28 02:07:35
  • Location: UK
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 03:23:11 (permalink)
0
Hi Dersu,
Noticed you adjusting the peripheral power down registers PMD.
Maybe worth a quick check that you haven't switched off the peripheral.
T Yorky.
#8
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 04:20:31 (permalink)
0
tmr_suresh
if there is no clock signal then chances are  input/output  pps  configuration .
please look the sample code below for spi3/spi4
 
PPSUnLock;
iPPSInput(IN_FN_PPS_SDI3 ,IN_PIN_PPS_RP124); //RG12 PIN 139 // SPI3
iPPSOutput(OUT_PIN_PPS_RP113,OUT_FN_PPS_SDO3); //RG1 PIN 128
iPPSOutput(OUT_PIN_PPS_RP112,OUT_FN_PPS_SCK3); //RG0 PIN 129

iPPSInput(IN_FN_PPS_SDI4 ,IN_PIN_PPS_RP108); //RF13 PIN 57 // SPI4
iPPSOutput(OUT_PIN_PPS_RP97,OUT_FN_PPS_SDO4); //RF1 PIN 97
iPPSOutput(OUT_PIN_PPS_RP96,OUT_FN_PPS_SCK4); //RF0 PIN 96
PPSLock;




hi tmr_suresh, I redid the definitions again, but no joy. Master is using the hardware pins, so I just set the TRIS on those - no PPS needed for master.
 
T Yorky
Hi Dersu,
Noticed you adjusting the peripheral power down registers PMD.
Maybe worth a quick check that you haven't switched off the peripheral.
T Yorky.



hi T Yorky, they look ok, 
PMD1 = 00001111011111001111 in binary
Bits 4 and 5 are SPI2 and UART1, the one further up is timer 1
setting the PMD's was an attempt out of desperation, the SPI pins are shared with some other peripherals than ADC so I thought they might be interfering - although the datasheet only mentions to disable ADC's.
DS70616G-page 194
bit 5 U1MD: UART1 Module Disable bit
1 = UART1 module is disabled
0 = UART1 module is enabled
bit 4 SPI2MD: SPI2 Module Disable bit
1 = SPI2 module is disabled
0 = SPI2 module is enabled

#9
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 06:51:13 (permalink)
4 (1)
Dersu Uzala
In the reference manual for SPI (DS70005185A) it is written that SCK needs to be set as input and output, I am curious if this still needs to be set if I use the dedicated hardware pins for SPI2.

 
For the SPI2 no.  As the manual says, "If the device has a Peripheral Pin Select (PPS) feature, the SCKx pin must
be mapped as both input and output in Master mode."  Meaning if you are using the SPI through the PPS system the SCK pin needs to be mapped as both an input and an output.  For SPI2 which has dedicated pins this is not an issue.
 
 
Dersu Uzala
I changed the code as above and put two led indicators to each write and read sections. The code gets stuck at while(!SPI2STATbits.SPIRBF); CONT_LED_0_LAT never goeas low


Wait... is that on the slave or the master???  I thought you said you couldn't get the debug to work on the master?
#10
T Yorky
Super (Thick) Member
  • Total Posts : 522
  • Reward points : 0
  • Joined: 2012/08/28 02:07:35
  • Location: UK
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 07:14:41 (permalink)
0
Hi Dersu,
As Belmerjd has pointed out, SPI requires configuring with PPS. Are you sure you are not confusing I2C (SCL2) with SPI (SCK2)?
T Yorky
#11
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 07:17:19 (permalink) ☼ Best Answerby Dersu Uzala 2014/11/13 14:27:44
4 (1)
OH DEAR ME!!!!  I just noticed on the master side you enabled the SPI interrupt but you don't have an interrupt function written for it and you also never enabled the SCK pin in the SPI config....  More than likely the reason you never see your LED change state is when you first power up the master it goes through your code and makes ONE transmission the very first time and then hangs.  The reason is you've enabled the SPI2 interrupt and the default created by the configuration defines (unless you set them other wise) sets SISEL to 0b111 which translates to "Interrupt when the SPIx transmit buffer is full (the SPITBF bit is set)" And since you've not made an interrupt handler, I believe the default action is a reset.
 
So basically I believe the problem here is your processor starts up, runs the main, doesn't enable the SCK line so you don't see the one transmission it does do, writes to the SPI buffer which causes the SPITBF flag to be set, that triggers your interrupt, but you don't have an interrupt written so the ISR vector is set to reset the program...
 
On the master side either change this:
ConfigIntSPI2(SPI_INT_PRI_3 & SPI_INT_EN);

to this:
ConfigIntSPI2(SPI_INT_PRI_3 & SPI_INT_DIS);

 
 
OR
 
 
change the main to this:
    while (1) {
       if (OKtoSendData) { // <--- FROM TIMER1, TURNS ON EVERY 500ms
            CONT_LED_1_LAT = 1;
            LATEbits.LATE7 = 0; // SPI2 SS
            __delay_us(50);
            WriteSPI2(k);
        }

Add this:
void __attribute__ ((interrupt)) _SPI2Interrupt()  // <~~~~ Might double check this declaration(I was in a hurry)
{
           RX_data = ReadSPI2();
            LATEbits.LATE7 = 1; // SPI2 SS
            CONT_LED_1_LAT = 0;
            OKtoSendData = 0;
}

And change the SPI config to this:
    SPISTATValue = SPI_ENABLE &
                        SPI_IDLE_CON &
                        SPI_RX_OVFLOW_CLR &
                        BUF_INT_SEL_1;



 
Lastly, there is a config define you've missed.  Don't feel bad, it's right at the beginning of the header separated from the section that it really belongs in.  Here:
    SPICONValue = ENABLE_SDO_PIN &
                        ENABLE_SCK_PIN &           // <~~~~ This is the one you were missing
                        SPI_MODE16_ON &
                        SPI_SMP_OFF &
                        SPI_CKE_ON &
                        SLAVE_ENABLE_OFF &
                        CLK_POL_ACTIVE_HIGH &
                        MASTER_ENABLE_ON &
                        SEC_PRESCAL_7_1 &
                        PRI_PRESCAL_64_1;

 
#12
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 08:10:03 (permalink)
0
balmerjd
Dersu Uzala
In the reference manual for SPI (DS70005185A) it is written that SCK needs to be set as input and output, I am curious if this still needs to be set if I use the dedicated hardware pins for SPI2.

 
For the SPI2 no.  As the manual says, "If the device has a Peripheral Pin Select (PPS) feature, the SCKx pin must
be mapped as both input and output in Master mode."  Meaning if you are using the SPI through the PPS system the SCK pin needs to be mapped as both an input and an output.  For SPI2 which has dedicated pins this is not an issue.
 
 
Dersu Uzala
I changed the code as above and put two led indicators to each write and read sections. The code gets stuck at while(!SPI2STATbits.SPIRBF); CONT_LED_0_LAT never goeas low


Wait... is that on the slave or the master???  I thought you said you couldn't get the debug to work on the master?




it is still the master, that bit of code runs on the slave, the way I understood it from Susan's post is that the data sent needs to be cleared so I gave it a try.
 
I have since replaced the master dspic with a new one, now I can debug but the code still hangs at the same spot.
#13
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 08:13:01 (permalink)
0
balmerjd
OH DEAR ME!!!!  I just noticed on the master side you enabled the SPI interrupt but you don't have an interrupt function written for it and you also never enabled the SCK pin in the SPI config....  

Smile: Smile
 
I just saw your post, my reply window was open for a while and I posted the previous one without checking if there was a new post. Let me understand what you've written and I'll be back
#14
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 08:37:00 (permalink)
0
Dersu Uzala
it is still the master, that bit of code runs on the slave, the way I understood it from Susan's post is that the data sent needs to be cleared so I gave it a try.
 
I have since replaced the master dspic with a new one, now I can debug but the code still hangs at the same spot.



You might want to go with the interrupt based code I suggested.  I also just noticed that you are operating in enhanced mode, so there is an 8-level FIFO to contend with.  SPIxRBF only gets set when the FIFO is full, i.e. there could be 1, 3, or even 7 byte/words to read out and SPIxRBF still won't get set.  So what you would need to do is either add FIFO_BUFFER_DISABLE to the SPIFRAMEValue or, change the while statement to while(SPI2STATbits.SRXMPT);
 
If you use the interrupt based code though that won't be a problem.
#15
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/13 14:27:24 (permalink)
0
finally it is working - I used the interrupt code. I can send from master and receive from slave. I need to play around a bit more.  Thank you very much for your help. I hope I wont but I'll probably be back soon for some DMA questions.
 
Which is the setting for enhanced mode, I sure didn't do it on purpose.
 
 
 
#16
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/14 05:16:50 (permalink)
0
It is the SPIBEN bit in the SPIxCON2 register.  Setting it to 0 puts the port in Legacy mode which makes the port act like the SPI ports that are in the dsPIC33F and PIC24F series chips.  Setting it to 1 puts the port in Enhanced Buffer mode.
 
The two main differences is how the data is handled and how interrupts are generated.
In Legacy Mode:
 - The transmit/receive buffer is one level (one trasmission) deep.  That is, when you write to the SPIBUF register, that one write fills it until the transmission starts then it becomes empty again and can be loaded with 1 more byte/word that will be held until the next transmission can be started.  Once a transmission completes, the receive buffer will have one byte/word in it, is full, and must be emptied before the completion of the next transmission or a collision will occur and SPIxSTAT.SPIROV will get set, the new incoming transmission that completed will be discarded and (my experience) the port gets disabled until you clear the flag.
 - If enabled, the port will generate an interrupt upon the completion of each transmission.
 
In Enhanced mode:
 - The transmit and receive buffers are an 8-level deep FIFO.
 - An interrupt can be generated on a number of different conditions and buffer statuses.
 - A number of bits in the SPI registers now have or have altered functionality. i.e. SPIxSTAT.SPIBEC is only implemented in enhanced mode, but SPIxSTAT.SPIRBF which would be set after every transmission in legacy mode now is only set when all 8 levels in the receive FIFO have data in them to be read.
 
I would HIGHLY suggest you carefully read over the SPI manual: Here
And then go over the SPI section in your specific processor's manual: Here
 
Keep in mind that when you are using the Peripheral headers like spi.h for the configuration defines that ANY BITS that you don't specificaly set one way or another with those defines gets set to one!
i.e. if you look at the spi.h file and the defines for SPIxCON2
#define  FRAME_ENABLE_ON        0xffff  //Frame SPI support enable        
#define  FRAME_ENABLE_OFF       0x7fff  //Frame SPI support Disable      

#define  FRAME_SYNC_INPUT       0xffff  //Frame sync pulse Input (slave) 
#define  FRAME_SYNC_OUTPUT      0xbfff  //Frame sync pulse Output (master)

#define FRAME_POL_ACTIVE_HIGH   0xffff  //Frame sync pulse is active-high 
#define FRAME_POL_ACTIVE_LOW    0xdfff  //Frame sync pulse is active-low

#define FRAME_SYNC_EDGE_COINCIDE 0xffff  //Frame sync pulse coincides with first bit clock
#define FRAME_SYNC_EDGE_PRECEDE  0xfffd  //Frame sync pulse precedes first bit clock

#define FIFO_BUFFER_ENABLE      0xffff  //FIFO buffer enabled
#define FIFO_BUFFER_DISABLE     0xfffe  //FIFO buffer disabled

As you can see, anything that you don't specifically set a certain way with one of those defines all get set to ones.  In your case you used only the FRAME_ENABLE_OFF declaration, which clears FRMEN but sets SPIFSD, FRMPOL, FRMDLY, and SPIBEN.  Now, since you were turning framing support off, those other registers don't really matter, but that last one does.
 
The moral here?  Once you've picked a PIC always read the Errata before designing with it, and then always read the device specific manual and go over the registers for the modules you intend to use so that you know what all bits are implemented on your device, and what they do.  If you have any more detailed questions after that, then you go consult the module specific manual.
#17
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/16 07:07:09 (permalink)
0
thanks balmer for the info
 
I dont usually use ready peripheral headers, that was a part of the attempt to get the thing running, assuming it would be easier to solve the problem. I have since reverted to setting the con/stats bits manually.
 
The spi seems to be running in the sense it transmits and receives. I am using SCK/SDO and SDI, SS is disabled and the bits set accordingly. FIFO is disabled. Below are the current settings

 
// MASTER SPI CONF *****************************************************************
 
void Init_SPI() {
 
SPI2STATbits.SPIEN = 0; // 
 
// INTERRUPT ************************************************************************
IFS2bits.SPI2IF = 0; // Clear the Interrupt flag
IEC2bits.SPI2IE = 0; // Disable the interrupt
IPC8bits.SPI2IP = 3; // Interrput priority
 
// SPIxCON1 *************************************************************************
SPI2CON1bits.DISSCK = 0; // Internal SPIx clock is enabled 
SPI2CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI2CON1bits.MODE16 = 1; // Communication is word-wide (16 bits)

SPI2CON1bits.CKE = 0; // Serial output data changes on transition from active clock state to Idle clock state
SPI1CON1bits.SSEN = 0; // SSx pin is not used for Slave Select
SPI2CON1bits.CKP = 0; // Idle state for clock is a low level; active state is a high level
SPI2CON1bits.MSTEN = 1; // MASTER MODE
SPI2CON1bits.SMP = 0; // Input data is sampled at the middle of data output time
 
SPI2CON1bits.SPRE = 7; // Secondary Prescale bits (Master mode) = 1:1
SPI2CON1bits.PPRE = 0; // Primary Prescale bits (Master mode) = 64:1 --> 70/8 = ~9 mhz
 
// SPIxCON2 *************************************************************************
SPI2CON2bits.FRMEN = 0; // Framed SPIx support is disabled
SPI2CON2bits.SPIBEN = 0; // Enhanced buffer is disabled (Legacy mode)
 
// SPIxSTAT *************************************************************************
SPI2STATbits.SPIEN = 1; // Enable SPI module (SPI1STATbits.SPIEN=?)
SPI2STATbits.SPIROV = 0; // Clear overflow
 
IFS2bits.SPI2IF = 0; // Clear the Interrupt flag
IEC2bits.SPI2IE = 1; // Enable the interrupt
 
}
 
 
 
// SLAVE SPI CONF *****************************************************************
 
void Init_SPI() {
 
SPI1STATbits.SPIEN = 0; // Disable SPI if already set (?)
 
// INTERRUPT ************************************************************************
IFS0bits.SPI1IF = 0; // Clear the Interrupt flag
IEC0bits.SPI1IE = 0; // Disable the interrupt
IPC2bits.SPI1IP = 3; // Interrput priority
 
// SPIxCON1 *************************************************************************
SPI1CON1bits.DISSCK = 0; // Internal SPIx clock is enabled (Master only!)
SPI1CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI1CON1bits.MODE16 = 1; // Communication is word-wide (16 bits)
 
SPI1CON1bits.CKE = 0; // Serial output data changes on transition from active clock state to Idle clock state
SPI1CON1bits.SSEN = 0; // SSx pin is not used for Slave Select
SPI1CON1bits.CKP = 0; // Idle state for clock is a low level; active state is a high level
SPI1CON1bits.MSTEN = 0; // MASTER MODE
SPI1CON1bits.SMP = 0; // Input data is sampled at the middle of data output time
SPI1CON1bits.SPRE = 7; // Secondary Prescale bits (Master mode) = 1:1
SPI1CON1bits.PPRE = 0; // Primary Prescale bits (Master mode) = 64:1 --> 70/8 = ~9 mhz
 
// SPIxCON2 *************************************************************************
SPI1CON2bits.FRMEN = 0; // Framed SPIx support is disabled
SPI1CON2bits.SPIBEN = 0; // Enhanced buffer is disabled (Legacy mode)
 
// SPIxSTAT *************************************************************************
SPI1STATbits.SPIROV = 0; // Clear overflow
SPI1STATbits.SPIEN = 1; // Enable SPI module (SPI1STATbits.SPIEN=?)
 
IFS0bits.SPI1IF = 0; // Clear the Interrupt flag
IEC0bits.SPI1IE = 1; // Enable the interrupt
 
}
 

 
But I have a curious problem I cant understand;
I have two different cases 
Case 1: Master has a counter that starts from 0 and increases by 1 after each transmit. The counter value is what is being transmitted to the slave. The slave then displays this value through UART. (SPI2 master, SPI1 slave)

 
// MASTER MAIN *******************************
 
unsigned int cntr;
cntr = 0;
 
while (1) {
 
if (OKtoSendData) {                              // <---- From Timer1, sets to true every 1 sec
 
SPI2BUF = cntr;
LED_1 = 1;
cntr++;
if (cntr == 50) cntr= 0;
}
 
}
 
 
 
// MASTER INTERRUPT **************************************
 
void __attribute__((__interrupt__, no_auto_psv )) _SPI2Interrupt(void) {
IFS2bits.SPI2IF = 0;
t_data = SPI2BUF;                                // read data from SLAVE                    
LED_1 = 0;
OKtoSendData = 0;                               // Data sent, wait for timer to enable next send
}
 
 
 
// SLAVE MAIN ********************************************
 
while (1) {
 
if (sendSPI) {                                      // From SPI interrupt, gets set when data is RCVD from master
LED_1 = 1;
sprintf(tempData, "SPI: %5u \t Cntr: %5u\r\n", datard, k);     // datard is set in INTRPT, data from MASTER
UART_Send(tempData);
LED_1 = 0;
SPI1BUF = k;                                    // SLAVE side counter, send to master
k++;
sendSPI = 0;
 
}
 
 
 
// SLAVE INTERRUPT *************************************
 
void __attribute__((__interrupt__, no_auto_psv )) _SPI1Interrupt(void) {
IFS0bits.SPI1IF = 0;
datard = SPI1BUF;                          // get data from MASTER
sendSPI = 1;                                  // data RCVD send to UART
}
 

In this case, the master counter rcvd from the slave is "meesed up", but there is a repeating pattern. What I send and receive are as such;
M    Slave
1    17 
2    34
3      1
4    19 
5    36 
6      3 
7    20 
8    37 
9     4 
10    22 
11    39
...     ...
 
Case 2: The slave is the one generating the counter. The master receives the counter value, adds 10 to it and sends it back to the slave, the slave displays the received value through UART. (Same code as above, only that the RCVD value from SLAVE gets set to SPIBUF

 
// MASTER MAIN *******************************
 
unsigned int cntr;
cntr = 0;
 
while (1) {
 
if (OKtoSendData) {                              // <---- From Timer1, sets to true every 1 sec
 
SPI2BUF = 10 + t_data;                        // <---- ADD 10 the value RCVD from SLAVE and send it back
LED_1 = 1;
cntr++;
if (cntr == 50) cntr= 0;
}
 
}

In this case everything works as expected, the master receives the values by an offset of two in terms of number of transmissions since only at the second transmission from master, does the master get the slave value
Master    Slave
10        0
10        1
10        2
11        3
12        4
...
 
Also instead of the counter increasing, if I keep it constant like cntr = 123, and keep the loop going, the from the start I get the correct value from the slave.
 
I cant quite understand what is going on here. I thought it might be typecasting but all that is sent and received are unsigned int. Aslo I thought I needed to swap LSB and MSB on the receive side but the values come out correct when I dont when I send a constant value. 
post edited by Dersu Uzala - 2014/11/16 07:11:48
#18
balmerjd
Super Member
  • Total Posts : 554
  • Reward points : 0
  • Joined: 2011/03/31 09:18:20
  • Location: Urbana, Ohio
  • Status: offline
Re: dspic33e SPI no clock 2014/11/17 07:12:02 (permalink)
0
Are you sure your processors are both running at the same speed?  This is really starting to sound like a synchronization problem.  It sounds like your slave is running significantly slower than your master is and as  result is having trouble keeping up with the SPI ports. If both processors are running at 70MIPS with a 64:1 pre-scaler then the output frequency should be somewhere around 1.09 MHZ, which is well below the bandwidth limit of the PPS port pins (which is usually around 10MHz).
 
So lets take a step back.  We'll call your current master M1 and the slave S2.  If I understand you correctly, if you set M1 as Master and S2 as slave you get errors in your received SPI data.  However, if you set M1 as slave and S2 as master things work ok?
 
It really sounds like something is out of sync here, because the master is what controls the timing.  I would check two things.
1.)  Make sure that the processors are truly running at the speed you think they are. (set up a timer for a known value and toggle an output and measure the period on a scope.
2.) Measure the Clock frequency on the SPI ports with a scope.
 
Do these for both setups (M1 as master and S2 as slave, and M1 as slave and S2 as Master) and see if you notice any differences.
 
Oh, one last note.  In your files you list;
SPI1CON1bits.CKE = 0; // Serial output data changes on transition from active clock state to Idle clock state
This is backwards.From the SPI manual Page 8:

0 = Serial output data changes on transition from Idle clock state to active clock state (see bit 6)
 Just for LOLs you might even try setting SKE to 1 on both ends just to see if it makes a difference.
#19
Dersu Uzala
New Member
  • Total Posts : 20
  • Reward points : 0
  • Joined: 2011/11/24 05:09:16
  • Location: 0
  • Status: offline
Re: dspic33e SPI no clock 2014/11/17 10:51:28 (permalink)
0
I've been trying different CKE/CKP variations, the slave messes up if I set CKE = 1. I have also switched from SPI2 (hardware) to PPS SPI1 on the master since I think I burnt the SDO pin on SPI2 while trying to hook the logic analyzer. I think I had a short. (The below occurrences were also witnessed on SPI2 too, so the short didnt cause the unexpected behaviour.). I have also disabled SDO on the slave, so I get no data back from slave, but I still read it on the master to free the buffer. I did check the clock speed, the logic analyzer reads 1.09mhz
 
M1 - S2 were always master and slave, I never switched them. What I did was;
- send a value to master from slave
- add 10 to it in master
- send it back to slave
- send it to UART from slave 
 
One thing I've noticed is that I'm transmitting 32 bits, not 16,  even though I'm sending one unsigned integer. I am going to try to attach the logic signals capture. 
 
If I send the value over and over again it gets transmitted to the slave just fine. If I try to send the incremented counter, the first 16bits on the logic analyzer match to what I see on the UART, the second 16bits (where they come from I have no idea) are larger by 2 than the original (why would it get incremented - no clue)
 
I didnt know there was a lower limit, I intentionally set the clock low to avoid problems, will try with a higher clock later on.
 
In the below images:
1.jpg - a constant hex of 0xBF82 was sent over, the received value matches the sent
 
2.jpg - counter starting from 0 incremented by one was sent after each increment. The first 16bits matches what was received on the UART, second 16 bits unknown origin :)... The counter values are still messed up. Here is what I send and receive:
0 - 0
1 - 72
2 - 144
3 - 216
4 - 288
 
All this said, I'll try increasing the clock and repeat the above ...
post edited by Dersu Uzala - 2014/11/18 00:22:49

Attached Image(s)

#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5