1

I am Using PIC24FJ128GB202 I want to communicate with a slave device which does not need to respond. So configuration is as follows enter image description here

I have written code as

    /* 
 * File:   main.c
 * Author: Nikhil
 *
 * Created on September 18, 2015, 2:59 PM
 */

#include <stdio.h>
#include <stdlib.h>
#define FCY 16000000UL
#include <xc.h>
#include <libpic30.h>
#include<GenericTypeDefs.h>
#include <p24FJ128GB202.h>

_CONFIG4(DSWDTPS_DSWDTPS5 & DSWDTOSC_LPRC & DSBOREN_OFF & DSWDTEN_OFF & DSSWEN_OFF & PLLDIV_PLL8X & I2C1SEL_DISABLE & IOL1WAY_OFF)
_CONFIG3(WPFP_WPFP63 & SOSCSEL_OFF & WDTWIN_PS75_0  & BOREN_OFF & PLLSS_PLL_FRC & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPSTARTMEM) //& PLLSS_PLL_FRC
_CONFIG2(POSCMD_NONE & WDTCLK_LPRC & OSCIOFCN_ON  & FCKSM_CSDCMD & FNOSC_FRCPLL  & ALTRB6_RETAIN & ALTCMPI_CxINC_RX & WDTCMX_WDTCLK & IESO_OFF)//& FNOSC_FRCPLL
_CONFIG1(WDTPS_PS1024 & FWPSA_PR128 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & LPCFG_ON & GCP_OFF & JTAGEN_OFF)



void __attribute__((__interrupt__,__auto_psv__)) _SPI1Interrupt(void);


void SPI_write()
{
PORTAbits.RA2 =0;
    SPI1BUFL = 0xAAAA;
   }
void SPI_delay()
{
    short i;
    for(i=0;i<8;i++)
    ;


}
void SPI_config(){
    SPI1CON1Lbits.SPIEN = 0 ;
    __builtin_write_OSCCONL(OSCCON & 0xbf);         // Unlock PPS
    RPOR1bits.RP2R = 7;                             //SPI SDO1
    RPOR1bits.RP3R = 8;                             //SPI SCK1
    SPI1STATLbits.SPIROV =0;                        //OVERflow Flag reset
    SPI1CON1Lbits.MSTEN = 1;                        //SPI Master
    SPI1CON1Lbits.MODE = 1;                         //16- bit Data transfer
    SPI1CON1Lbits.CKE = 0;
    SPI1CON1Lbits.CKP =0;   
    __builtin_write_OSCCONL(OSCCON | 0x40);      // Lock PPS
    SPI1CON1Lbits.SPIEN = 1 ;
}

static inline void
init_io(void)
{
        /* Digital Mode */
        ANSA = 0;
        ANSB = 0;

        /* Reset O/P */
        LATB = 0;
        LATA =0 ;

    /* O/D Off */
    ODCA = 0;
    ODCB = 0;

       /* Define Outpot port */
        TRISB = 0 ;
        TRISA =0 ;
}


int main (void)

{
    CLKDIVbits.CPDIV = 0x01;
    init_io();
    SPI_config();
    //////////////////////////////// SPI Interrupt ////////////////////////////////
    _SPI1IP = 1;
    _SPI1IF =  0;
    SPI1IMSKLbits.SRMTEN = 0x01;    
    _SPI1IE =1;


//////////////////////////////// main code //////////////////////////////////////////


  while(1)
    {
      SPI_write();
      __delay_ms(1);
    }
   return 0;

}





void __attribute__((__interrupt__, __auto_psv__)) _SPI1Interrupt(void)
{
    // Clear SPI1 1 interrupt flag
    _SPI1IF = 0;

     PORTAbits.RA2 =1;




}

I am receiving clock and data properly. But the port A (slave select) goes high while SPI transfer.

enter image description hereI have tried millions of combinations of delays

I have even tried SPIwrite as:

void SPI_write()
{
PORTAbits.RA2 =0;
short temp,temp1; 

    SPI1BUFL = 0xAAAA;
    __delay_ms(1);
    temp = SPI1BUFL;
    temp1 =SPI1BUFH;
    while(!SPI1STATLbits.SPIRBF);
   }

and also tried to enable disable pin before and after writing
Like

PORTAbits.RA2 =0;
SPI_write();
PORTAbits.RA2 =1;

Still same error

Please please please!!! help I am getting frustrated with this error

nikhil patil
  • 142
  • 1
  • 12
  • Change every instance of where you write to a port using e.g. `PORTAbits` and instead use the corresponding latch register. For example, instead of `PORTAbits.RA2 = 1` write `LATAbits.LATA2 = 1`. Then see if the behaviour changes and amend your question if necessary. – Roger Rowland Sep 26 '15 at 19:20
  • HI Roger I tried that also. – nikhil patil Sep 26 '15 at 19:41
  • The execution of PORTAbits.RA2 /LATCHAbits.LATA2 happens before the data is transferred. I tried adding delay and while () statement but same result. Please note I have grounded the sdi pin of pic. One more strange thing is that if I write while(!SPI1STATLbits.SPIRBF) the programs stops at this statement and data is only transferred once. – nikhil patil Sep 26 '15 at 19:46
  • Normal procedure is to wait until the transmit buffer is available, then write the next symbol. After **all** writes, you have to wait until the SPI is not busy anymore. There should be status-flags for both conditions, if the SPI is not double-buffered, there is only a busy/transmitter empty flag available/required. A delay -even worse with CPU cycles is a very bad idea. – too honest for this site Sep 26 '15 at 22:09
  • I tried using while(!SPI1STATELbits.SRMT) i.e. shift register empty and while(SPI1STATELbits.SPIBUSY) I am getting same result I m so frustrated now :( – nikhil patil Sep 26 '15 at 22:13
  • Is there another thread/interrupt handler running which modifies the port? You might have some interference on port accesses here (not sure if the PIC24 inhibits this). – too honest for this site Sep 27 '15 at 02:09
  • I do have interrupt on portA4 not on porta2 will this aafect. .? – nikhil patil Sep 27 '15 at 02:30
  • Make sure read-modify-write of a port is always atomic. C does not guarantee, but your implementation and CPU/hardware might. Also: did you set SS to output? – too honest for this site Sep 27 '15 at 13:32
  • What happens if you let the MCU handle the SPI line for you? Any reason why you need to do it manually? – Lundin Sep 28 '15 at 07:02
  • If spi module handles it I get the same result as shown on oscilloscope – nikhil patil Sep 28 '15 at 12:44
  • Any reason you are writing to PORTA from inside the ISR and main both? Or is that just some remains from your debug attempts? – Lundin Sep 28 '15 at 15:03
  • Its one of the attempts I have done. basically i have tried doing like this: main(){ PORTA =0; SPIWRITE(); PORTA=1; } METHOD 2: SPIWRITE(){ PORTAbitsA2 = 0; SPIBUFL = 0xAAAA; while(!SPI1STATLbits.SPIBUSY) ; // Tried using SPISRMT(Transmit shift register),SPISRBUF(Recieve buffer) PORTAbitsA2 =1; } method 3 is mentioned in above code is there any other method i can try? – nikhil patil Sep 28 '15 at 15:12

1 Answers1

2

I think I may have the same issue, but I was wanting the Slave Select to assert while the transfer is going on and then de-assert between transfers. However, like you I could not get it to de-assert. I finally figured out a way to have it de-assert between transfers. I poll the SS pin to see when it starts to de-assert. This means that that internal ssp state machine has moved to that "done" state, does not see a way to pipeline multiple transfers, and will now de-assert the SS pin.

Since I am always going to be signal work transfers and I will never do large transfers, I will be moving this while statement inside of the SPI1_Exchange16() call. The SPI1_Excahnge16 call is a modified version of the SPI1_Exchange() call, which does a 16 bit transfers instead of 8.

Below is my example code and I attached a trace showing the impact of the while statement on the SPI bus. You can see the first two transfers have SS de-asserting between transfers.Affect of waiting for SS1 to de-assert

SPI1_Exchange16( &txData16[0], &rxData16[0] );
while (SS1_GetValue()==0){};
SPI1_Exchange16( &txData16[1], &rxData16[1] );
while (SS1_GetValue()==0){};
SPI1_Exchange16( &txData16[1], &rxData16[1] );  
// NO WHILE STATEMENT
SPI1_Exchange16( &txData16[1], &rxData16[1] );
// NO WHILE STATEMENT
SPI1_Exchange16( &txData16[1], &rxData16[1] );
// NO WHILE STATEMENT
Ken 99
  • 19
  • 3