Electronic – Problem with SPI communication (PIC24H)

picspi

I'm trying to communicate with a NRF24L01 transceiver module with a PIC24HJ128GP202. Besides all the code, here is the important part:

void NRF_Config()
{
  NRF_WriteRegister(0x02, 0x01); //PIPE 0 ENABLE
  NRF_ActivateSR();
  NRF_WriteRegister(0x1D, 0x06); //FEATURE REG - Enable Dynamic Payload && Enable ACK Payload
  NRF_WriteRegister(0x1C, 0x01); //ENABLE DYNAMIC PAYLOAD PIPE0
  NRF_WriteRegister(0x00, 0x5A); //CONFIG REG
  Delay(Delay_2ms);
  NRF_EN(); //CHIP ENABLED PIN = TRUE
}

with the WriteRegister function being:

unsigned char NRF_WriteRegister(unsigned char reg, unsigned char data)
{
   SPI1_BEGIN(); //CHIP SELECT = LOW  (START COMMUNICATION)

   IFS0bits.SPI1IF = 0;
   while (SPI1STATbits.SPITBF);
   WriteSPI1(0x20 | reg);
   while (!IFS0bits.SPI1IF);

   IFS0bits.SPI1IF = 0;
   while (SPI1STATbits.SPITBF);
   WriteSPI1(data);
   while (!IFS0bits.SPI1IF);

   SPI1_END(); //CHIP SELECT = HIGH (END COMMUNICATION)
   return ReadSPI1();
}

This works fine (at least it seems to work). Code runs ok and O'scope shows CS pin going low, then 2 groups of 8 pulses in the SCK pin followed by CS going high.

Then I have this:

unsigned char NRF_PutTXPayload(unsigned char *data, char len)
{

   if (len > TX_DATA_SIZE)
       return 0;
   SPI1_BEGIN();

   //SEND BYTE 1
   IFS0bits.SPI1IF = 0;
   while (SPI1STATbits.SPITBF);
   WriteSPI1(0xA0);
   while (!IFS0bits.SPI1IF);

   //SEND BYTE 2
   IFS0bits.SPI1IF = 0;
   while (SPI1STATbits.SPITBF);
   WriteSPI1(0xEF);
   while (!IFS0bits.SPI1IF);

   //SEND BYTE 3
   IFS0bits.SPI1IF = 0;
   while (SPI1STATbits.SPITBF);
   WriteSPI1(0xEF);
   while (!IFS0bits.SPI1IF);

  SPI1_END();
  return ReadSPI1();

}

As you can see this function above is a modified version of the original one I wanted to use. I'm currently not using those arguments and I used to have a For loop to send variable length group of bytes. Then I came into to this version above because it was freezing my PIC somewhere inside the For loop. Then I realize that if I keep only the first two blocks (SEND BYTE 1 and SEND BYTE 2) it's ok. When I add the third one, it freezes the PIC.

I know that I could reduce my code when taking care of flag bits but I copied exaclty the same lines from the WriteRegister function on purpose to make sure it should work.
Also, it should work because first I reset interrupt flag; then I wait for TX empty buffer to start copying; then I simply write to TX buf; and then I wait to interrupt flag which means transmission has finished. Altough not being the best/fastest way to do that, I think it should work well, but it does not.

It's strange because it works with 2 bytes but not with three. The O'scope shows CS pin going Low, then it shows the three groups of 8 clocks in SCK pin but the CS pin never goes back high (and the PIC is freezed).

Any idea what might be happening?

Best Answer

One of the errata on that chip is:

  1. SPI Module The SPI transmit buffer full (SPITBF) flag does not get set immediately after writing to the buffer.

So perhaps try a delay (maybe 10 NOPs or something like that) before testing the SPITBF flag. There does not appear to be an official work-around.