Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Problems with SPI timing - Arduino to Pic.

Status
Not open for further replies.

Pommie

Well-Known Member
Most Helpful Member
I currently have a 16F18326 programmed as a slave device and an Arduino Leonadro as the master. Everything works fine if I print the received character on the Arduino but becomes garbage if the prints are removed. Replacing the print with a 4uS delay fixes the problem again. The pic is running at 32MHz and is using the SSP interrupt to process everything. I don't understand why these delays are necessary.

Arduino send routine,
Code:
void sendBuff(){
  uint8_t i,dummy;
  SPI.beginTransaction (SPISettings (1000000, MSBFIRST, SPI_MODE0));  // 1 MHz clock, MSB first, mode 0
  digitalWrite(SS,LOW);
  dummy=(SPI.transfer(buff[0]));
  delayMicroseconds(4);
  for(i=0;i<sizeof(buff);i++){
    buff[i]=(SPI.transfer(buff[i+1]));
    delayMicroseconds(4);
  }
  Serial.println(buff);
  digitalWrite(SS,HIGH);
  SPI.endTransaction (); 
}

And the Pic interrupt code,
Code:
void __interrupt() inter(void){
    static char buffCount;
    char temp;
    if(SSP1IF && SSP1IE){
        if(buffCount>=32){  // stop buffer overflowing
            temp=SSP1BUF;   //throw away
        }else{
            temp=SSP1BUF;
            SSP1BUF=buff[buffCount];
            buff[buffCount++]=temp;
        }
        SSP1IF=0;
    }
    if(IOCAF2){         //A2 is Slave Select input
        IOCAF2=0;       //interrupt only on falling edge
        buffCount=0;
        dummy=SSP1BUF;  //prepare to receive data
        SSP1IF=0;       //clear pending interrupt
        SSP1IE=1;       //allow SSP to interrupt
    }
}

Note RA2 (Slave select) is setup to interrupt on rising edges only so I can make sure it stays in sync. I first thought that the problem may only be with the first byte due to the RA2 interrupt but it happens with all bytes. Note the pic receives all data correctly with or without the delays.

Mike.
 
You appear to be loading data to the SPI buffer on the transmit side, without checking if buffer space is available?

I'm guessing the added delay allows the previous byte to be sent so the buffer has emptied and there are then no overruns.
 
How do I check if the buffer is empty on the Arduino?

Mike
Edit, how can the function return a value if the transmit hasn't completed?
 
How do I check if the buffer is empty on the Arduino?

Sorry, no idea, I've never used the Arduino.

It does appear to wait for the transfer to complete as it can return a value, as you say; I was getting mixed up between code fragments.

Possibly the Arduino is transferring too fast for the PIC to process things properly and the inter-byte delay is compensating for that?

If that is the case, I'd guess it should work without the delay if you eg. half the transfer clock frequency?

Or if it's that close to being critical, try a bit of optimisation, eg. you can remove a numeric comparison and some redundant lines in the PIC side:

C:
void __interrupt() inter(void){
    static char buffCount;
    char temp;
    if(SSP1IF && SSP1IE){
       
        temp=SSP1BUF;

        if(!(buffCount & 0x20)){  // stop buffer overflowing      
            SSP1BUF=buff[buffCount];
            buff[buffCount++]=temp;
        }
        SSP1IF=0;
    }
    if(IOCAF2){         //A2 is Slave Select input
        IOCAF2=0;       //interrupt only on falling edge
        buffCount=0;
        dummy=SSP1BUF;  //prepare to receive data
        SSP1IF=0;       //clear pending interrupt
        SSP1IE=1;       //allow SSP to interrupt
    }
}
 
I've sped up the Pic code by allowing the buffer to overflow (made it bigger). I slowed the Arduino down to 250k but I still need the small delays. I can speed the Arduino up to 2MHz without any problem if I have the delays. It's as though it's using some kind of callback to fill the buffer. Guess I'll just use it "as is" with the delays.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top