0
\$\begingroup\$

I have little bit problem to transmit and receive data with nrf24l01. I use spi communication to communicate my MCU and nrf24l01. My spi communication is working. But i cannot receive any data from nrf24l01.

This is my configuration to drive nrf24l01:

enter image description here

My Hardware configuration:

enter image description here

CE is pin in my nrf24l01. nrf24l01 has IRQ pin, but i don't use it. I make CS pin LOW if i want to access data from MCU to nrf24l01 and make it HIGH again when communication is finished.

This is my code to access spi from MCU to nrf24l01:

#define CS_HI           GPIO_SetBits(SPI_CS, CSN)
#define CS_LO           GPIO_ResetBits(SPI_CS, CSN)

unsigned short SendSPI(unsigned short val)
{
 SPI_I2S_SendData(SPI2, val);
 while(SPI_I2S_GetITStatus(SPI2, SPI_I2S_FLAG_TXE)==SET);
 SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_TXE);

 return(SPI_I2S_ReceiveData(SPI2));
}

void AccessSPI(unsigned char Cmd, unsigned char *pStatus, unsigned char *ptrBuff, unsigned char Total, unsigned char Operation)
{
 unsigned char m, temp;

 temp=Cmd;
 CS_LO;

 *pStatus=SendSPI(temp);        // Send Command
 if (Operation==kWriteSPI)
    {
     for (m=0; m<Total; m++)
        {
         temp=*ptrBuff;
         SendSPI(temp);
         ptrBuff++;
        }
    }
 else
    {
     for (m=0; m<Total; m++)
        {
         temp=SendSPI(0);
         // ptrbuff = &var (ptrbuff has address of value)
         *ptrBuff=temp; // store value from temp to ptrbuff value
         ptrBuff++; // increase address of ptrbuff
        }
    }
 CS_HI;
 }

Perhaps, this one can more help to understand my problem. This is my example code to make nrf24l01 configuration:

#define CE1_HI          GPIO_SetBits(PeriphSCE, SCE)
#define CE1_LO          GPIO_ResetBits(PeriphSCE, SCE)

void InitNRF24L01(void)
{
 unsigned char statusNRF,cmd;

 RFChan=20;
 Addr[0]=123;
 Addr[1]=0;
 Addr[2]=0;
 Addr[3]=0;
 Addr[4]=0;

 CE1_LO;
 CS_HI;
 //SCK_LO;
 //MOSI_LO;

 // Power Up
 Delay(100);
 cmd=(1<<PWR_UP)|(1<<PRIM_RX)|(1<<EN_CRC);
 AccessSPI(W_REGISTER|CONFIG, &statusNRF, &cmd, 1 , kWriteSPI);
 Delay(100);

 // Enable Auto Ack
 cmd=(1<<ENAA_P0);  //|(1<<ENAA_P1)|(1<<ENAA_P2)|(1<<ENAA_P3)|(1<<ENAA_P4)|(1<<ENAA_P5);
 AccessSPI(W_REGISTER|EN_AA, &statusNRF, &cmd, 1 , kWriteSPI);

 // Enable Data Pipe
 cmd=(1<<ERX_P0);   //|(1<<ERX_P1)|(1<<ERX_P2)|(1<<ERX_P3)|(1<<ERX_P4)|(1<<ERX_P5);
 AccessSPI(W_REGISTER|EN_RXADDR, &statusNRF, &cmd, 1 , kWriteSPI);

 // 3 bytes width
 cmd=(k3BytesAddr<<AW0);
 AccessSPI(W_REGISTER|SETUP_AW, &statusNRF, &cmd, 1 , kWriteSPI);

 // Retransmit
 cmd=0;     //(15<<ARC)|(0<<ARD);
 AccessSPI(W_REGISTER|SETUP_RETR, &statusNRF, &cmd, 1 , kWriteSPI);

 // 2 MBps-0dB-LNA On
 cmd=(k0dBm<<RF_PWR)|(kLNAGain<<LNA_HCURR)|(kRate2Mbps<<RF_DR);
 AccessSPI(W_REGISTER|RF_SETUP, &statusNRF, &cmd, 1 , kWriteSPI);

 // RF Channel
 cmd=RFChan;
 AccessSPI(W_REGISTER|RF_CH, &statusNRF, &cmd, 1 , kWriteSPI);

 // Set RX Address
  AccessSPI(W_REGISTER|RX_ADDR_P0, &statusNRF, &Addr[0], 5 , kWriteSPI);
  // Set TX Address
  AccessSPI(W_REGISTER|TX_ADDR, &statusNRF, &Addr[0], 5 , kWriteSPI);

  cmd=32;                                                                           // Total Payload 0 32 bytes
  AccessSPI(W_REGISTER|RX_PW_P0, &statusNRF, &cmd, 1 , kWriteSPI);

  cmd=(1<<EN_ACK_PAY);
  AccessSPI(W_REGISTER|FEATURE, &statusNRF, &cmd, 1 , kWriteSPI);
  cmd=0;
  AccessSPI(W_REGISTER|DYNPD, &statusNRF, &cmd, 1 , kWriteSPI);

  FlushTXFIFO();
  FlushRXFIFO();
  cmd=(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT);                                                // Clear all status latched
  AccessSPI(W_REGISTER|STATUS, &statusNRF, &cmd, 1 , kWriteSPI);
}

void EnableReceive(void)
{
    unsigned char statusNRF, cmd;

    CE1_HI;
    cmd=(1<<RX_DR);
    AccessSPI(W_REGISTER|STATUS, &statusNRF, &cmd, 1 , kWriteSPI);
}

enum eStatus ReceiveData2(void)
{
    unsigned char statusNRF, addr, temp, cmd, output[32];
    unsigned char *pdat;

    //AccessSPI(R_REGISTER|STATUS, &temp, &statusNRF, 1, kReadSPI);

    temp=(1<<PWR_UP)|(1<<PRIM_RX)|(1<<EN_CRC);
    AccessSPI(W_REGISTER|CONFIG, &statusNRF, &temp, 1 , kWriteSPI);

    AccessSPI(R_REGISTER|FIFO_STATUS, &temp, &statusNRF, 1, kReadSPI);
    if ((statusNRF & (1<<RX_EMPTY))==0)
    {
         AccessSPI(R_REGISTER|STATUS, &temp, &statusNRF, 1, kReadSPI);
         addr=(statusNRF >> 1) & 0x07;
         if (addr<6)
         {
             pdat=output;
             AccessSPI(R_RX_PAYLOAD, &temp, pdat, 32, kReadSPI);
              /*int i;
              for(i=0; i<32; i++)
              {
                  USART_SendData(USART2, output[i]);
                  Delay(1);
              }*/

              FlushRXFIFO();
              return(kDataExist);
         }
         cmd=(1<<RX_DR);
         AccessSPI(W_REGISTER|STATUS, &statusNRF, &cmd, 1 , kWriteSPI);
         return(kNoData);
    }
    return(kNoData);
}

void FlushTXFIFO(void)
{
    unsigned char statusNRF, cmd;

    AccessSPI(FLUSH_TX, &statusNRF, &cmd, 0 , kWriteSPI);
}

void FlushRXFIFO(void)
{
    unsigned char statusNRF, cmd;

    AccessSPI(FLUSH_RX, &statusNRF, &cmd, 0 , kWriteSPI);
}

void Delay(unsigned int val)
{
 unsigned int m, n;

 for (m=0; m<val; m++)
    {
     for (n=0; n<1000; n++);
    }
}

void DelayuS(unsigned int val)
{
 unsigned int   m, i;

 for (m=0; m<val; m++)
 for (i=0; i<4; i++);
}

void SendData2(unsigned char *pDat)
{
    unsigned char statusNRF, cmd;

    cmd=(1<<PWR_UP)|(1<<EN_CRC);
    AccessSPI(W_REGISTER|CONFIG, &statusNRF, &cmd, 1 , kWriteSPI);
    AccessSPI(W_TX_PAYLOAD, &statusNRF, pDat, 32 , kWriteSPI);
    CE1_HI;
    DelayuS(kWaitBurst); // wait 80uS, i have checked in oscilloscope
    CE1_LO;
    DelayuS(280); // wait 280uS
    FlushTXFIFO();
}

and this is my main program:

unsigned char dataNRF[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                        11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
                        21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
                        31, 32};
int main(void)
{
    // nyalakan NRF24l01
    InitSPI();
    InitNRF24L01();
#if defined(receiver)
    EnableReceive();
#endif

    while(1)
    {
#if defined(receiver)
        ReceiveData2();
#elif defined(transmitter)
        unsigned char *temp = &(dataNRF[0]);
        SendData2(temp);
#endif
    }
}

I was think, my problem is in my configuration. I read again in my nrf24l01 datasheet, but i cannot solved it. I need some help to solved this. Thank you.

UPDATE 1: Perhaps, somebody can check my spi configuration. if i have something wrong with my code, i need some advice. I'm used STM32F103 as MCU. And this is my initialisation for my spi.

void InitSPI(void)
{
 SPI_InitTypeDef SPI_InitStruct;
 GPIO_InitTypeDef GPIO_InitStructure;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
#if defined(minsys)
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
#elif defined(audio)
 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
 GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
 GPIO_PinRemapConfig(GPIO_Remap_FSMC_NADV, DISABLE);
#endif

 GPIO_InitStructure.GPIO_Pin = SCLK|MOSI;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = CSN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI_CS, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = MISO;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = SCE;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(PeriphSCE, &GPIO_InitStructure);

 SPI_InitStruct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16;
 SPI_InitStruct.SPI_CPHA=SPI_CPHA_1Edge;
 SPI_InitStruct.SPI_CPOL=SPI_CPOL_Low;
 SPI_InitStruct.SPI_DataSize=SPI_DataSize_8b;
 SPI_InitStruct.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
 SPI_InitStruct.SPI_FirstBit=SPI_FirstBit_MSB;
 SPI_InitStruct.SPI_Mode=SPI_Mode_Master;
 SPI_InitStruct.SPI_NSS=SPI_NSS_Soft;

#if defined(minsys)
 SPI_Init(SPI2, &SPI_InitStruct);
 SPI_Cmd(SPI2, ENABLE);
#elif defined(audio)
 SPI_Init(SPI1, &SPI_InitStruct);
 SPI_Cmd(SPI1, ENABLE);
#endif
}

UPDATE 2: This is my simple code to read STATUS Register, it will return 0x00 right now. What procedure that i need to write or read register in nrf24l01?

CE1_LO;
CS_HI;
unsigned char temp, statusNRF;

// Power up
Delay(100); // 72 ms , checked in my oscilloscope
temp=(1<<PWR_UP)|(1<<PRIM_RX)|(1<<EN_CRC);
AccessSPI(W_REGISTER|CONFIG, &statusNRF, &temp, 1 , kWriteSPI);
Delay(100); // 72 ms , checked in my oscilloscope, more than enough

temp=(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT);
AccessSPI(W_REGISTER|STATUS, &statusNRF, &temp, 1 , kWriteSPI);
AccessSPI(R_REGISTER|STATUS, &temp, &statusNRF, 1, kReadSPI);
USART_SendData(USART2, statusNRF); // I send to serial, and always read 0x00
\$\endgroup\$
  • \$\begingroup\$ Your hardware configuration doesn't show the CE pin, but you're using a flow that seems to assume it is used and asserted appropriately. Start by verifying that you can read the receiver's status register. Then explain what is going on with the CE, and post your code and the actual connections. \$\endgroup\$ – Chris Stratton Jul 25 '17 at 5:19
  • \$\begingroup\$ Thank you. I just forget to write my NRF24l01 pin that i used. \$\endgroup\$ – calvin limantara Jul 25 '17 at 5:26
  • \$\begingroup\$ to mr. Chriss Stratton, I have finished to edit my question. If you still don't understand with my question, please reply this post immediately. Thank you. \$\endgroup\$ – calvin limantara Jul 25 '17 at 6:08
  • \$\begingroup\$ How are you sure that your SPI communication works? Have you tried reading the configuration register after boot? It should give you a value of 0x08. And for a user to be notified about a direct mention to him, you should use the @ in front of the username in your comment. \$\endgroup\$ – nickagian Jul 25 '17 at 7:25
  • 1
    \$\begingroup\$ Well, the fact that you read 0 from the STATUS register seems again odd. In my opinion you have a problem with the SPI communications. I'd advise you to start from the basics. Write a code where you just wait for your power-up time and then you read the CONFIG register. Don't over-complicate things. You don't need to write any register: The SPI communication should work even if the chip is in power down mode. Then debug your SPI code until you get 0x08 as a read value from this minimal code. As you seem to have an oscilloscope, I'd strongly advise you to use it during the process. \$\endgroup\$ – nickagian Jul 25 '17 at 8:47
0
\$\begingroup\$

I don't have right now my code in front of me, so that I can compare your process with mine, but I have two comments:

(1) It's ok if you don't use the IRQ pin, but you have to know what you are doing. I think your ReceiveData2 is wrong. Please read comment (b) on page 58 of the datasheet to understand how the process works.

In essence, you have to setup the chip in receive mode but then you have to wait until the RX_DR bit of the STATUS register is set. This will happen when new data have been received and are available to be read from the RX_FIFO. You don't do this. I don't say this is the reason why you don't receive anything, but this is the clean way to do it.

If you had used the IRQ pin, you could just wait for an interrupt to come on this pin and then go to read the rx fifo.

(2) You should also check your transmitting part. I hope you are aware that the receive and transmit settings have to match. Mainly check the receive and transmit addresses.

\$\endgroup\$
  • \$\begingroup\$ Right now, i can identify status from my FIFO_STATUS Register. From transmitter i get x01. it say my TX FIFO has a data. So i conclude that my transmitter is ready to transmit my data. But, when i check my FIFO_STATUS register at my Receiver, it gives x11. So i conclude my receiver doesn't receive any data from my transmitter. I have updated my ReceiveData function. maybe you can check it. I have set RX_DR register but it doesn't give any effect. Do you have any idea to solve this? \$\endgroup\$ – calvin limantara Jul 26 '17 at 4:45
  • \$\begingroup\$ Is that possible? if you transmit data and received by receiver, data in RX_PAYLOAD is empty? (FIFO_STATUS in receiver give value x00) \$\endgroup\$ – calvin limantara Jul 26 '17 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.