Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with slave mode SPI in dsPIC33EP512 MU810

Status
Not open for further replies.

kappa_am

Full Member level 6
Joined
Jul 16, 2012
Messages
331
Helped
19
Reputation
38
Reaction score
19
Trophy points
1,298
Location
Vancouver
Activity points
3,859
Hi all,
I am planning to connect two dsPIC33ep512MU810 via SPI connection. The master works properly, but I cannot get any data in the buffer of slave one and it remains 0. I checked the clock pin chip selection pin using pin change interrupt, and they work properly. Even I disabled the SS, but still nothing. I don't know what I am missing. The program I wrote is rather large (multiple ADC with DMA, PWMs, etc) so I extract SPI section to avoid wasting your time. it is as below:
Code:
#include "Config.h"
 unsigned short COMND, RAMP_SHAPE, LOP, FRQ_JMPN, SLP_CMP;
 float FTHETA, DELTHETA;
 volatile bit ACCDCC, ROT_DIR, REV, FRT_LOP, JMP_LOP, JMP_OC;
 int* EXAM;
 far unsigned int BUFF1A [4], BUFF1B[4], BUFF[2], BUFF2A[4], BUFF2B[4];
 int* pv1;
 unsigned int ReadWordArr[64];
 unsigned int WriteWordArr[64];

void SPI4_INT() iv IVT_ADDR_SPI4INTERRUPT {
   LATD=SPI4BUF;                                       // 
  IFS7bits.SPI4IF=0;
}

  void SPI4EER() iv IVT_ADDR_SPI4ERRINTERRUPT {
  SPI4STATbits.SPIEN = 0; // Disable SPI module
  SPI4STATbits.SPIROV=0; //Clear the Receive Overflow Flag
  IFS7bits.SPI4EIF = 0; // Clear the SPI2 Error Interrupt Flag
  SPI4STATbits.SPIEN = 1; // Enable SPI module
}

 void CHNG() iv IVT_ADDR_CNINTERRUPT ics ICS_AUTO {
  IFS1bits.CNIF = 0;

  //LATD^=0xFFFF;
}


 void main() {
    IPC4=0x2000 |IPC4;
   Osc_Config(140);
   //////////////////////////////////////////////////////
   ANSELB=0x0030; 
   TRISB=0x003C;
   ANSELD= 0x0000;
   TRISD  = 0x0000;
   ANSELG = 0x0000;
   TRISG  = 0x1000;
   OSCCON=OSCCON & 0xFFDF;  //Unlock I/O
   RPINR31 = 0x227C;       //RPI34=SCK, RPI124=SDI,
   RPINR32= 0x0023;      // RPI35=SS
   RPOR15=0x0022;        //RP126=SDO
   OSCCON=OSCCON | 0x0020;   //LOck I/O

   CNENG.b12=1;
   IFS1.b3=0;
   IEC1.b3=1;
  ///////////////////////////////////////////////////////////////
  SPI4BUF=0;
   IFS7bits.SPI4EIF = 0; // Clear the Error Interrupt flag
   IEC7bits.SPI4EIE = 0; // Enable the error interrupt
  SPI4CON1=0x0500;
  SPI4STATbits.SPIROV=0;
  SPI4STAT=0x8000;
  IFS7bits.SPI4EIF = 0;
  IEC7bits.SPI4EIE = 1;

    PMD3.b10=1;
   ////////////////////////////////////////////////////////////////

   while (1) {
      LATD=SPI4BUF;
    Delay_us(10);
     }}

Osc configuration :
Code:
  void Osc_Config(unsigned int CLKFREQ) {
  OSCCON=0x33E0;
  CLKDIV=0x0006;       //PLL's Divider Configuration (divided by CLKDIV<4:0>+2)
  PLLFBD=(CLKFREQ-1)*2;             //PLL's Feedback Congiguration (multiply by PLLFBD+2)
  //OSCTUN=0;
  //REFOCON=0;
  ACLKCON3=0xE4A0;        //Axuliary OSC PLL Configuration 0x00F0 post divider; 0x000F prescale
  ACLKDIV3=7;}

The configuration of master and slave is similar. I don't know what I have missed. I would be grateful if you give me a hint.

Thank you
 

Have you actually looked at the signals with an oscilloscope? that might give you a clue. You could try writing a simpler piece of code to just exercise the SPI port to make sure your basic routine is working.
 

Hi Barry,
Thanks for your response.
Actually, I have looked many times by oscope everything looks fine on the master side. I have data on slave-side's pins. and pins response to the data ( examined by change interrupt) but unfortunately, slave's buffer remains zero. Actually, I was planning to use SPI+DMA; now, I have deleted all routines except a simple SPI. But still, the problem exists. I have changed input pins and mapped them on other pins, still no success. Really I have no clue what I am missing. 5 days of struggling but no success. :)
 

I'm not really a SW guy, so I can't help you there, but your comment "I have changed input pins..." gives me pause. Aren't there dedicated pins for the SPI port? You can't arbitrarily assign any pin as a SPI pin, can you?
 

In some MCUs we can map pins of peripheral units to almost arbitrary I/O pins.

anyway, thank for taking time and intention to help. This itself means a lot. :)
 

In some MCUs we can map pins of peripheral units to almost arbitrary I/O pins.

anyway, thank for taking time and intention to help. This itself means a lot. :)

Then I would first suspect that there's a problem with your mapping. that should be easy to determine by using the debugger. In fact, you should be able to resolve this problem, whatever it is, with the debugger.
 

That is not the correct way to unlock and then relock the PPS registers - there is a complete sequence yo need to go through that is best handled in assembler (the instructions MUST be executed in sequence and without interruption) or - preferably - using any macro that your compiler might provide.
Fortunately for you, the default is for the PPS registers to be unlocked on reset.
You are also not setting the OSCCON register correctly. It also requires an unlock sequence to set the NOSC bit and then trigger the oscillator switch. Again there may well be macros to assist you but you really should read the data sheet for how to do this properly. Again, that should not stop the SPI slave from working as it will use the masters SCK signal, but it may stop the rest of the code from running at the speed you expect.
If you are using an interrupt to see when a value has been received then don't keep reading from the buffer in your main loop. I must admit I have no idea how this would impact the way the SPI peripheral works but this is certainly not how you should be designing you code.
I see that you are not ever enabling the SPI Rx ISR. Are you relying on reading the SPIxBUF in your main loop? If so then you should only be updating the LAT when you are told by the SPI that it has received a value (SPIRBF goes high). As you are only waiting 10uSec between reads, if you do get a value it will only be on the output pins for...10 uSec!
Susan
 

Hi Susan,
All these were desperate tries to get any value in SPI buffer. I had got the master side with the same MCU working, but in slave side, the buffer remains zero all times not even gets a wrong value! I create new project very simple but still nothing! really confused what I am missing.

My compiler is MikroC

Code:
#include "Config.h"

unsigned int COMND;
void SPI4_INT() iv IVT_ADDR_SPI4INTERRUPT {
   LATD=SPI4BUF;
  IFS7bits.SPI4IF=0;}

  void SPI4EER() iv IVT_ADDR_SPI4ERRINTERRUPT {
  SPI4STATbits.SPIEN = 0; // Disable SPI module
  SPI4STATbits.SPIROV=0; //Clear the Receive Overflow Flag
  IFS7bits.SPI4EIF = 0; // Clear the SPI2 Error Interrupt Flag
  SPI4STATbits.SPIEN = 1; // Enable SPI module
  }

 void CHNG() iv IVT_ADDR_CNINTERRUPT ics ICS_AUTO {
  IFS1bits.CNIF = 0;

  //LATD^=0xFFFF;
}
 void main() {
    IPC4=0x2000 |IPC4;
   Osc_Config(140);
   TIMER1_Config();
   //////////////////////////////////////////////////////
   ANSELB=0x0030; // *******ansel
   TRISB=0x003C;
   ANSELD= 0x0000;
   TRISD  = 0x0000;
   ANSELG = 0x0000;
   TRISG  = 0x1000;
   Unlock_IOLOCK();
   PPS_Mapping_NoLock(126, _OUTPUT, _SDO4);     // Set pin RG14 to be Output, and map SD04 to it
   PPS_Mapping_NoLock(34, _INPUT, _SCK4IN);  // Set pin RB2 to be Output, and map SCK4 to it
   PPS_Mapping_NoLock(124, _INPUT,  _SDI4);     // Set pin RG12 to be Input,  and map SDI4 to it
   PPS_Mapping_NoLock(35, _INPUT,  _SS4IN);
   Lock_IOLOCK();
   CNENG.b12=1;
   IFS1.b3=0;
   IEC1.b3=1;
  ///////////////////////////////////////////////////////////////
  COMND = SPI1BUF;
  SPI4BUF=0;
   IFS7bits.SPI4EIF = 0; // Clear the Error Interrupt flag
   IEC7bits.SPI4EIE = 0; // Enable the error interrupt
   IPC30=IPC30|0x3400;
  SPI4CON1=0x0500;
  SPI4STATbits.SPIROV=0;
  SPI4STAT=0x8000;
  IFS7bits.SPI4EIF = 0;
  IEC7bits.SPI4EIE = 1;
    PMD3.b10=1;
   //////////////////////////////////////////////////////////////
   while (1) {
asm NOP;
     }}

Could you please take a look and share your advice. I would be really grateful.

Thanks
 

Sorry, the above code is not correct. Actually, the implemented code is:

Code:
#include "Config.h"

unsigned int COMND;
void SPI4_INT() iv IVT_ADDR_SPI4INTERRUPT {
   LATD=SPI4BUF;

  IFS7bits.SPI4IF=0;}

  void SPI4EER() iv IVT_ADDR_SPI4ERRINTERRUPT {
  SPI4STATbits.SPIEN = 0; // Disable SPI module
  SPI4STATbits.SPIROV=0; //Clear the Receive Overflow Flag
  IFS7bits.SPI4EIF = 0; // Clear the SPI2 Error Interrupt Flag
  SPI4STATbits.SPIEN = 1; // Enable SPI module
    // LATD^=0xFFFF;
  }

 void CHNG() iv IVT_ADDR_CNINTERRUPT ics ICS_AUTO {
  IFS1bits.CNIF = 0;

  //LATD^=0xFFFF;
}
 void main() {
    IPC4=0x2000 |IPC4;
   Osc_Config(140);
   TIMER1_Config();
   //////////////////////////////////////////////////////
   ANSELB=0x0030; // *******ansel
   TRISB=0x003C;
   ANSELD= 0x0000;
   TRISD  = 0x0000;
   ANSELG = 0x0000;
   TRISG  = 0x1000;

   Unlock_IOLOCK();
   PPS_Mapping_NoLock(126, _OUTPUT, _SDO4);     // Set pin RG14 to be Output, and map SD04 to it
   PPS_Mapping_NoLock(35, _INPUT, _SCK4IN);  // Set pin RB2 to be Output, and map SCK4 to it
   PPS_Mapping_NoLock(124, _INPUT,  _SDI4);     // Set pin RG12 to be Input,  and map SDI4 to it
   PPS_Mapping_NoLock(34, _INPUT,  _SS4IN);
   Lock_IOLOCK();
   CNENB.b3=1;
   IFS1.b3=0;
   IEC1.b3=1;
  ///////////////////////////////////////////////////////////////
  COMND = SPI1BUF;
  SPI4BUF=0;
   SPI4STAT=0x0004;
   IFS7bits.SPI4IF = 0;
   IEC7bits.SPI4IE = 1;
   IFS7bits.SPI4EIF = 0; // Clear the Error Interrupt flag
   IEC7bits.SPI4EIE = 0; // Enable the error interrupt
   IFS7bits.SPI4EIF = 0;
  IEC7bits.SPI4EIE = 1;
   IPC30=IPC30|0x3400;
  SPI4CON1=0x0580;
  SPI4STATbits.SPIROV=0;
    SPI4CON2=0x0001;
  SPI4STAT.SPIEN=1;


    PMD3.b10=1;
   //////////////////////////////////////////////////////////////
   while (1) {
asm NOP;
     }}
 
Last edited:

While it is good that you have started to use the \SS\ again (it really is a good thing to ensure against stray SCK pulses), why have you started to use the enhanced buffer??? If you are having problems getting the basic operation to go, why start adding complicating factors!
I would suggest that you drop all of the code, including the interrupts, and do a very simple setup of the SPI peripheral and use the main loop to check for the SPIRBF bit being set and then read the SPIxBUF. Get that working first and then add in other complicating factors later.
Can you check the signal on the actual pin (not the PCB trace) for the SDI line? There could be a dry joint there.
Also, put a value other than 0x00 into the SPIxBUF before the exchange takes place and look at the SDO line while the master is sending. If you don't see data then it shows that the \SS\ or SCK signal is not getting through.
Also check with the scope that the \SS\ line is not going high before the end of the exchange.
I see you are using 16-bit exchanges - you have not shown the master code but I assume that it is also in 16-bit mode.
You have the CKE bit set high - that should not impact receiving but make sure that the master is expecting the data to transition according to the CKP/CKE bit settings you have.
I must admit I've not heard of this on an SPI slave for devices with PPS, but try mapping the SCK line to a I/O pin and map BOTH the SCK in and SCK out to that pin. In 'master' mode, that can be needed to get the receiver working.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top