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 SPI+DMA in dsPIC33EP512MU810

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 have implemented SPI connection between two dspic33EP512mu810 and 814 MCUs with DMA. receiving DMAs are ping pong mode and sending DMA is continuous ping pong disabled. At first I transmit numbers 0-63 two times if both buffers are equal the setup proceeds with converting 4 channels ADC. Master transfers 4 words (results of ADC conversion), and slave transfers received ADC results (saved on worlds 0-4) and words 4-7 (their values equal to their order) All works well, but some times the bits which are saved in the memory is shifted some bits. Fist, when I switch a load on or off adjacent to the circuit. Since I saw this problem first I turn a switching power supply ON, I checked every thing for noise problem, I add some filters on the power supply but the problem still exists. When I turn ON PWM of the slave ( no power switching component) the problem exacerbated, and the bits are shifted after a while (not fixed time).
I would be grateful if you share your opinion about solving this problem.


Regards,

The correct data:
1.jpg

The wrong data I got:
2.jpg3.jpg4.jpg5.jpg
 

My guess is that the noise is getting in to the SCK line and making it think that a clock pulse has been received (or masking one that really is there - depends which way the bits are shifted).
Also I'm guessing that you are not using the \SS\ or a framing pulse to 'window' when the valid SCK pulses are being sent.
Given that, use the \SS\ line and/or decouple the lines to prevent the noise.
It is s bit hard to see what is happening in your pictures - can you expand the timescale a bit so we can see the SCK transitions better?
Also you have not told us anything about the SPI connections and setup.
I would also suggest that you sort this out without the DMA component if you can. Firstly get reliable SPI exchanges going and then add the DMA aspect later on.
Susan
 

Hi, Thank you for your response; I have solved all the problems. Now, the SPI without DMA is working and SPI with both transfer and receiver DMA is working but I need a sPI with just receiving DMA. I cannot figure out an SPI with just receiving DMA. I write a program as follows, but when the DMA gets turned ON the SPI stops working.
I would be grateful if you share your comments.

Thank you.


Code:
 unsigned int LOP, PARAMIC[64], ReadWordArr[64], VARPARM[6], ACVSET, LOP2, PARAMIC1[4];
 far unsigned int BUFF1A [4], BUFF1B[4], BUFF[2], BUFF2A[8], BUFF2B[8], BUFF3A[4], LOP1;
 unsigned long SETADD;

void SPI3_INT() iv IVT_ADDR_SPI3INTERRUPT {
  // LATD=SPI3BUF;
  IFS5bits.SPI3IF=0;}

  void SPI3EER() iv IVT_ADDR_SPI3ERRINTERRUPT {
  SPI3STATbits.SPIEN = 0; // Disable SPI module
  SPI3STATbits.SPIROV=0; //Clear the Receive Overflow Flag
  IFS5bits.SPI3EIF = 0; // Clear the SPI2 Error Interrupt Flag
  SPI3STATbits.SPIEN = 1; // Enable SPI module
  }



void Timer3Int() iv IVT_ADDR_T3INTERRUPT {
  T3IF_bit = 0;             // clear T2IF
}


 void DMA0Int() iv IVT_ADDR_DMA0INTERRUPT {

 IFS0bits.DMA0IF=0;
 }
 
 void DMA1Int() iv IVT_ADDR_DMA1INTERRUPT {
 unsigned int DMAREC =0;
 if (DMAREC==0)
 {asm nop;}
 else{asm nop;}
 DMAREC^=1;
 IFS0bits.DMA1IF=0;
 }
 
  void DMA2Int() iv IVT_ADDR_DMA2INTERRUPT {
 unsigned int DMAREC2 =0;
 if (DMAREC2==0)
 {asm nop; }
 else{asm nop;}
 DMAREC2^=1;
 IFS1bits.DMA2IF=0;
 }

 void main() {
  LOP2=0;
  OSCCON=0x33E0;
  CLKDIV=0x000E;       //PLL's Divider Configuration (divided by CLKDIV<4:0>+2)
  PLLFBD=278;             //PLL's Feedback Congiguration (multiply by PLLFBD+2)
  //IPC2 = IPC2 | 0x0001;   // interrupt priority level = 1  timer
 /*T3IF_bit = 0;             // clear T2IF
  T3IE_bit = 1;             // enable Timer2 interrupts
  T3CON = 0x8000;           // Timer2 ON, prescaler 1:64
  PR3   = 700;            // 100ms interrupt*/
  TRISB=0x003F;
  ANSELB=0x003F;
  ANSELE= 0x0000;
  TRISE  = 0xFFFF;
  CNPDE = 0xFFFF;
  TRISF  = 0x0000;
  TRISJ=0xFEFF;
  AD1CSSH=0x0000;           //which one to scan higher word
  AD1CSSL=0x0000;           //which one to scan lower word
  AD1CHS0=0x0202;           //Channel 0 negative is Vref, and A and B intervals input 2
  AD1CHS123=0x0101;         //Channel 1,2,3 negatives are Vref, and A and B intervals input 3 , 4, 5, respectively
  AD1CON4=0x0010;           //DMA Enable and number of buffer per channel
  AD1CON3=0x0507;           //Sample time (N*TDA), Clock setup  TAD=N*TCY
  AD1CON2=0x820C;           // vref determination, all channels are active, increment DMA after 4 conversion, use select bit A
  AD1CON1=0xB04C;           // DMA address in the order of conversion, trigger pwm event
  AD1CON1bits.ADON=0;
  AD1CON2bits.BUFM=0;
  AD1CON4bits.ADDMAEN=1;
  DMA0CON=2;
  DMA0PAD= &ADC1BUF0;
  DMA0CNT=3;
  DMA0REQ=13;
  DMA0STAL=&BUFF1A[0];
  DMA0STAH=0x000;
  DMA0STBL=&BUFF1B[0];
  DMA0STBH=0x0000;
  IFS0bits.DMA0IF=0;
  IEC0bits.DMA0IE=1;
  DMA0CONBITS.CHEN=1;
  AD1CON1bits.ADDMABM=1;
  AD1CON2bits.SMPI=3;
  AD1CON4bits.DMABL=1;
  IFS0BITS.AD1IF=0;
  IEC0BITS.AD1IE=0;
  AD1CON1bits.ADON=1;

/////////////////////////////////////////////
     SETADD=0x055400-ACVSET; //ACVSET is multiply of 64
     FLASH_Read(0x055400, PARAMIC, 64);   
   ///////////////////////////////////////////////////////
   PARAMIC[0]= 32768;
   PARAMIC[1]= 300;
   PARAMIC[2]= PORTE &0x03FF;
   PARAMIC[3]= 3;
   
    for(LOP=4; LOP<13; LOP++){
     PARAMIC[LOP]= LOP;}


    PARAMIC[13]= 0x0000; 
   PARAMIC[14]= 0x0000; 
   PARAMIC[15]= 0x0000; 
   PARAMIC[16]= 0xFFFF; 
   PARAMIC[17]= 0;
   PARAMIC[18]= 0xFFFF; 
   PARAMIC[19]= 0xFFFF; 
   PARAMIC[20]= 1280;
   PARAMIC[21]= 0xFFFF;
   PARAMIC[22]= 0xFFFF;
   PARAMIC[23]= 64;
   PARAMIC[24]= 15;
   PARAMIC[28]= 280;
   PARAMIC[29]= 600;
   PARAMIC[30]= 2400;
   PARAMIC[25]= 30*64;
   PARAMIC[26]= 60*64;
   PARAMIC[27]= 75*64;
   PARAMIC[31]= 0x0018;
   PARAMIC[32]= 100;
   PARAMIC[33]= 15;
   PARAMIC[34]= 32768;
   PARAMIC[35]= 15; 
   PARAMIC[36]= 208; 
   PARAMIC[37]= 530; 
   PARAMIC[38]= 120;
   PARAMIC[39]= 208; 
   PARAMIC[40]= 10000; 
   PARAMIC[41]= 0; 
   PARAMIC[42]= 20;   
   PARAMIC[43]= 60*64;  
   for(LOP=44; LOP<64; LOP++){
   PARAMIC[LOP]= LOP;}// voltage  points
   //////////////////////////////////////////////////////////////////////////////
    SETADD=0x055400-ACVSET; //ACVSET is multiply of 64
    FLASH_Erase(0x055400);                //  whenever a change occures, save should be done
    FLASH_Write(0x055400, PARAMIC);
    ///////////////////////////////////////////////////////////////
    
       ///////////////////////////////////////////////
  Unlock_IOLOCK();
   PPS_Mapping_NoLock(99, _OUTPUT, _SDO3);     // Set pin RD5 to be Output, and map SD03 to it
   PPS_Mapping_NoLock(108, _OUTPUT, _SCK3OUT);  // Set pin RD3 to be Output, and map SCK3 to it
   PPS_Mapping_NoLock(41, _INPUT,  _SDI3);     // Set pin RD4 to be Input,  and map SDI3 to it
   Lock_IOLOCK();
  ///////////////////////////////////////////////
   SPI3CON1=0x0520;
   SPI3STAT=0x8000;
   SPI3CON2=0x0000;
   LOP1=0;
  LATJ.b8=0;
  while (LOP1==0){
   for (LOP=0; LOP<64; LOP++){
     SPI3_Write(PARAMIC[LOP]);
     delay_us(5);}
    delay_ms(500);
   for (LOP=0; LOP<64; LOP++){
     SPI3_Write(PARAMIC[LOP]);
     delay_us(5);}
    LOP=SPI3_Read(0x5050);
    delay_us(5);
    LOP=SPI3_Read(0x5050);
     delay_us(5);
   
     if(LOP==0x3333){
     LOP1=1;
   
     }}
     LATJ.b8=1;
  
      //////////////////////////////////////////////////////////////   Receive
    IFS0bits.DMA1IF=0;
    IEC0bits.DMA1IE=1;
    DMA1CON=0x0002; //continuous Ping-pong , null data feed
    DMA1PAD= &SPI3BUF;
    DMA1CNT=7;
    DMA1REQ=0x005B; //SPI3 Transfer is done
    DMA1STAL=&BUFF2A[0];
    DMA1STAH=0x000;
    DMA1STBL=&BUFF2B[0];
    DMA1STBH=0x000;
    IPC3= IPC3 | 0x0200;
    DMA1CON=0x8002;
/////////////////////////////////////////////// Value loaded form CNTRL board
  while (1)  {
   BUFF3A[1]=((BUFF1A[1]<<2) & 0xFFFC);
   BUFF3A[0]=27648+(BUFF1A[0]*10);
   BUFF3A[2]=PORTE & 0x03FF;
   BUFF3A[3]=BUFF2A[3];
   for (LOP=0; LOP<4; LOP++){
        LATJ.b8=0;
    SPI3_Write(BUFF3A[LOP]);
        LATJ.b8=1;
     delay_us(5);}
   for (LOP=0; LOP<4; LOP++){
     LATJ.b8=0;
    SPI3_Write(BUFF3A[LOP]);
     LATJ.b8=1;
     delay_us(5);}
    }}
 

What is in the SPI3_Write function? Is it blocking and/or does it also read the received value from the SPI buffer? If
If it reads the SPIBUF register then it might be interfering with the DMA operation.
It is generally not a good idea to capture the SPI interrupt while it is attached to a DMA channel as the DMA channel uses the flag to know when the operation is completed and it will control the IF bit itself. (Although I must admit that I can't see if you are setting the SPI IE bit in all of that code.)
My general rule is that, when you use DMA on a peripheral, then you leave it to the DMA to do all of the heavy lifting and you just look at the buffers.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top