Need help: nRF24L01 cannot receive after repower

hello, everyone

I want to use nRF24l01 module to communicate. Both board A and board B have a ATmega48 and a nRF24L01 module. VCC is 3.3V.Board A is configured as transmitter and board B as receiver.

After I programmed two MCUs they can work successfully. But if I cut the Power on board B and repower up it, board B can’t receive anything(RX_DR doesn’t set high).Then if I reset board A, they communicate again(RX_DR of nRF24L01 on board B set high).

what a strange thing!

Can anyone help me?

Thanks in advance.

It sounds like a software problem causing a deadlock condition.

Leon

But where is the problem? I have thought for one week more.

my code(part related to 24L01)

TX:


#define CE_0 do {PORTB &= ~(1<<2);} while(0)
#define CE_1 do {PORTB |= (1<<2);} while(0)							//CE <-> PB2

#define CSN_0 do {PORTB &= 0XEF;} while(0)
#define CSN_1 do {PORTB |= 0X10;} while(0)						//CSN <-> PB4 (SS)

//function: spi_init()
//description: intialize SPI
//para: void
//return value: void
void spi_init(void)
{
	SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR0);					//Enable SPI, MASTER Mode, Fosc/16
  	
	SPSR = 0;													

	CSN_1;
}


//function: send_spi()
//description: send a byte to SPI
//para: data: data to send
//return value: data returned from SPI
unsigned char send_spi(unsigned char data)
{
 	SPDR = data;
	
	while(!(SPSR & (1 << SPIF)));								//waiting finishing
	
	return SPDR;
}



//function: spi_wr_byte()
//description: send a byte to a register of nRF24L01 
//para: reg: instruction bits + register bits, value: data to send
//return value: status register value
unsigned char spi_wr_byte(unsigned char reg, unsigned char value)
{
 	unsigned char a;
	
	CSN_0;
   	
	a = send_spi(reg);			//select the register to write to
   	
	send_spi(value);             //write value to it
	
	CSN_1;

	return(a);            // return nRF24L01 status byte
}


//function: spi_rd_byte()
//description: read a byte from a register of nRF24L01 
//para: reg: instruction bits + register bits
//return value: the register value
unsigned char spi_rd_byte(unsigned char reg)
{
	unsigned char reg_val;
   	
	CSN_0;
   	
	send_spi(reg);            // select the register to read from..
   	
	reg_val = send_spi(0);    // ..then read register value
	
	CSN_1;
	
	return(reg_val);        // return register value
}



//function: spi_rd_buf()
//description: read some bytes from a register of nRF24L01 to a buf 
//para: reg: instruction bits + register bits, *pBuf: buf to storage data, byte: numbers of bytes to read
//return value: status register value
unsigned char spi_rd_buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)
{
 	unsigned char status = 0;
	unsigned char byte_ctr = 0;
 	
	CSN_0;
   	
	status=send_spi(reg);         			//select register to read from and read status byte
	
	for(byte_ctr=0; byte_ctr < bytes;byte_ctr++)
   		pBuf[byte_ctr] = send_spi(0);    	// Perform send_spi(0) to read byte from nRF24L01
	
	CSN_1;
	
	return(status);
}

//function: spi_wr_buf()
//description: write some bytes to a register of nRF24L01 from a buf 
//para: reg: instruction bits + register bits, *pBuf: buf to storage data, byte: numbers of bytes to write
//return value: status register value
unsigned char spi_wr_buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)
{
 	unsigned char status = 0;
	unsigned char byte_ctr = 0;
 	
	CSN_0;
 	
	status=send_spi(reg);    				//select register to write to and read status byte
	
	for(byte_ctr=0; byte_ctr < bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
  		send_spi(*pBuf++);
	
	CSN_1;
	
	return(status);
}




//function: nRF24L01_init()
//description: intialize nRF24L01
//para: void
//return value: void
void nRF24L01_init(void)
{
    spi_wr_byte(WRITE_REG + EN_AA, 0x00);	//disable AA

	//regi = spi_rd_byte(READ_REG + EN_AA);
	
	//spi_wr_byte(WRITE_REG + SETUP_RETR, 0x00);
	
	//spi_wr_byte(WRITE_REG + RF_CH, 0x08);
	
	spi_wr_byte(WRITE_REG + RX_PW_P0, 1); 	//payload width = 1
 	
	spi_wr_byte(WRITE_REG + CONFIG, 0x7A);	//Interrupt not reflected one IRQ pins, Power up, PTX mode

	CE_0;
}



int main(void)
{
 	_delay_ms(3);
	
	
	PORTB = 0x10;				
	
	DDRB = 0XB5;					//SCK, SS, MOSI, PB2(CE) and  PB0(LED) as output, others as input					
													
		
	PORTA = 0x00;
	
	DDRA = 0xFF;	
	
	spi_init();
		
	
	nRF24L01_init();

	_delay_ms(2);
	
		
	spi_wr_byte(FLUSH_TX, 0);	

	tx_buf[0]='j';
	
	spi_wr_buf(WR_TX_PLOAD, tx_buf, 1); 
	
	CE_1;

	_delay_us(30);

	CE_0;	
	
		
	//eeprom_write(1, 1);
	
	while(1)
	{	
		sta = spi_rd_byte(READ_REG+STATUS); 				// read register STATUS's value
				
 		
		if(sta & (MAX_RT | TX_DS))
		{
			spi_wr_byte(WRITE_REG+STATUS, sta);	// clear RX_DR or TX_DS or MAX_RT interrupt flag
			
			if(sta & MAX_RT)
			{
 				PORTB &= ~0x01;				//led : green

				PORTA |= 0x01;
			
				spi_wr_byte(FLUSH_TX, 0);
				
				//eeprom_write(1, sta);
				
				//test = spi_rd_byte(READ_REG+OBSERVE_TX);			
			}
 		
			else if(sta & TX_DS)
 			{
    			PORTB |= 0x01;				//led : red

				PORTA &= ~0x01;
			}
		
			
			//_delay_ms(500);
			
			spi_wr_buf(WR_TX_PLOAD, tx_buf, 1); 
	
			CE_1;

			_delay_us(20);

			CE_0;
		
			_delay_us(150);
		}	
  	}	
}





RX:

.....the same as TX code....

//function: nRF24L01_init()
//description: intialize nRF24L01
//para: void
//return value: void
void nRF24L01_init(void)
{
    spi_wr_byte(WRITE_REG + EN_AA, 0x00);

	//regi = spi_rd_byte(READ_REG + EN_AA);
	
	//spi_wr_byte(WRITE_REG + SETUP_RETR, 0x00);
	
	//spi_wr_byte(WRITE_REG + RF_CH, 0x08);
	
	spi_wr_byte(WRITE_REG + RX_PW_P0, 1); 	
 	
	//spi_wr_byte(WRITE_REG + EN_RXADDR, 0X01);

	spi_wr_byte(WRITE_REG + CONFIG, 0x7B);  	

	CE_0;
}


void display(void)
{
	PORTD = 0xFF;

	PORTA = Led_7[Dis_buff[Posit]];

	if(Point_on && (Posit == 2 || Posit == 4))
		PORTA |= 0x80;

	PORTD = Position[Posit];

	if(++Posit >= 6)
		Posit = 0;
}


ISR(TIMER0_COMP_vect)
{
	display();
}







int main(void)
{
 	_delay_ms(1);
	
	
	PORTB = 0x10;
	
	DDRB = 0XB5;					
													
		
	PORTA = 0x00;
	
	DDRA = 0xFF;	
	
		
	PORTD = 0x3F;

	DDRD = 0x3F;

	
	
	TCCR0 = 0x0B;				//8M/64 = 125kHz

	TCNT0 = 0x00;

	OCR0  = 0xF9;				//0xF9(249), (249+1)/125kHz = 2ms						

	TIMSK = 0x02;

	Posit = 0;	
	
	
	spi_init();
		
	
	nRF24L01_init();

	spi_wr_byte(FLUSH_RX, 0);
	
	_delay_ms(2);
	
		
	CE_1;

	
	sei();		
	
	while(1)
	{	
		
		//_delay_us(130);

		sta = spi_rd_byte(READ_REG+STATUS); 				// read register STATUS's value
		
		spi_wr_byte(WRITE_REG+STATUS, sta);	// clear RX_DR or TX_DS or MAX_RT interrupt flag
  		
		
		if(sta & RX_DR)    					// if receive data ready (RX_DR) interrupt
 		{
  			CE_0;				
			
			spi_rd_buf(RD_RX_PLOAD,rx_buf,1);// read receive payload from RX_FIFO buffer
    	
			spi_wr_byte(FLUSH_RX, 0);
			
			for(unsigned char i = 0; i < 6; i++)	//Dis_buff[i] for displaying on LED to observe whether receive or not
				Dis_buff[i] = 0;	
			
			//cli();
			//eeprom_write(1, sta);
			//sei();
			
			CE_1;
	
		}
 		
		
  	}	
}

ISR(TIMER0_COMP_vect){…} is the Timer0 Compare Match ISR(2ms), used for displaying data on LED.

MCU is changed to ATmega16L because it has a JTAG. (I try another MCU but still has problem)

Thank you, Leon.

Here’s some PIC test code of mine that works OK:

;***************************************************************
;Test.asm
;Tx/Rx test program for MiRF V2
;MCU: PIC16F88
;uses hardware 16F88 SSP module (hardware SPI)
;
;user interface
;LED		- RB5, output (pin 11)
;PB			- RA1, input (pin 18)
;
;nRF24L01 connections to 16F88
;
;IRQ		- RA0, input (pin 17)
;CE 		- RB0, output (pin 6)
;MISO/SDI	- RB1, input (pin 7)
;MOSI/SDO	- RB2, ouput (pin 8)
;CSN		- RB3, output (pin 9)
;SCK		- RB4, output (pin 10)
;***************************************************************

	errorlevel -302

#define IRQ 	0
#define	MISO 	1
#define MOSI 	2
#define	SCK		4
#define	CSN		3
#define	CE		0
#define	LED		5
#define PB		1


;defines for software SPI

#define SPI_SCK 4
#define SPI_SO 2
#define SPI_SI 1

#include	<p16f88.inc>


	CBLOCK 0x20
	scrA:	1	; scratch pad	0x20
	scrB:	1
	count
	RXDATA
	TXDATA
	status
	data_0
	data_1
	data_2
	data_3
	data_4
	ENDC

	org		0

	nop

;**************************************************************
;main program
;**************************************************************
	call	init
	banksel	PORTB
	call	flash_led


zzz:
	bcf		PORTB,CSN		;CSN low
	call	short_dly
	
	movlw	0x10			;send command (read configuration)
	movwf	TXDATA			;put in TXDATA
	call	spi_send_read	;send it
	call	short_dly

	call	spi_send_read
	movfw	RXDATA			;status is first byte received
	movwf	status			;save it
	call	short_dly


	call	spi_send_read
	movfw	RXDATA
	movwf	data_0
	call	short_dly

	call	spi_send_read
	movfw	RXDATA
	movwf	data_1


	call	spi_send_read
	movfw	RXDATA
	movwf	data_2


	call	spi_send_read
	movfw	RXDATA
	movwf	data_3

	call	spi_send_read
	movfw	RXDATA
	movwf	data_4

	nop
	bsf		PORTB,CSN		;CSN high
	nop
	goto	zzz

stop:
	goto	stop



aaa:

	BANKSEL	SSPSTAT
LOOP: 	
	BTFSS 	SSPSTAT, BF 	;Has data been received (transmit complete)?
	GOTO 	LOOP 			;No
	BCF 	STATUS, RP0 	;Specify Bank0
	MOVF 	SSPBUF, W 		;W reg = contents of SSPBUF
	MOVWF 	RXDATA 			;Save in user RAM, if data is meaningful
	MOVF 	TXDATA, W 		;W reg = contents of TXDATA
	MOVWF 	SSPBUF 			;New data to xmit

	goto	aaa


spi_send_read:
	banksel	PORTB
	bcf		PORTB,SPI_SCK	;SCK low
	movfw	TXDATA
	movlw	8				;8 bits to send
	movwf	count
sp1_1:
	rlf		TXDATA,f		;MS bit in C
	btfss	STATUS,C		;C = 0?		
	goto	spi_2			;no, jump
	bsf		PORTB,SPI_SO	;yes, output one
	goto	spi_3
spi_2:
	bcf		PORTB,SPI_SO	;output zero
spi_3:
	btfsc	PORTB,SPI_SI	;SPI_SI input low?
	goto	spi_4			;no, jump
	bcf		STATUS,C		;yes, clear carry bit
	goto	spi_5
spi_4:
	bsf		STATUS,C		;set carry bit
spi_5:
	rlf		RXDATA,f		;rotate RXDATA left
	bsf		PORTB,SPI_SCK	;SCK high to latch bit
	decfsz	count,f			;count = 0?
	goto	sp1_1			;no, loop back
	return					;yes, return


;***************************************************************
;initialisation
;***************************************************************
init:

	;oscillator setup
	BANKSEL	OSCCON
	MOVLW	0x70		; 8 MHz int. RC osc.
	MOVWF	OSCCON

WAIT1:
	BTFSS	OSCCON,2	; wait until freq. is stable
	GOTO	WAIT1

	;I/O setup
	BANKSEL PORTA 		; select bank of PORTA
	CLRF 	PORTA 		; Initialize ports by
	CLRF	PORTB		; clearing output data latches
	BANKSEL	ANSEL 		; Select Bank of ANSEL
	MOVLW	0x00 		; Configure all pins
	MOVWF	ANSEL 		; as digital
	BANKSEL TRISB
	MOVLW	0x02		; configure PORTB I/O (00000010)
	MOVWF	TRISB	
	MOVLW	0x01		;configure PORTA I/O (00000001)
	MOVWF	TRISA
	banksel	PORTB
	bsf		PORTB,CSN	;CSN high
	bcf		PORTB,CE	;CE low

	return

	;SPI setup
	BANKSEL	SSPSTAT
	MOVLW	0x40		;SPI master mode (01000000)
	MOVWF	SSPSTAT
	MOVLW	0x32		;enable SSP for SPI master mode, clock = OSC/64 (00110010)
	MOVWF	SSPCON

	RETURN


;******************************************************************
;flash LED five times
;******************************************************************
flash_led
	movlw	5
	movwf	count
flash1:
	BSF		PORTB,LED	;toggle LED
	call	dly
	BCF		PORTB,LED
	call	dly
	decfsz	count,f
	goto	flash1
	return

;****************************************************************
;transmit configuration
;****************************************************************
Tx_config:
	banksel	PORTA
	clrf	PORTA
	movlw	0x38
	movwf	TRISA
	bcf	PORTA,CE	;set config mode (CE = 0, CSN = 1)
	nop
	bsf	PORTA,CSN
	call	dly
	;send 24 bit configuration word 001000110100111000000100 (0x234E04) MS bit first
	movlw	0x23
	call	put_byte
	movlw	0x4E
	call	put_byte
	movlw	0x04
	call	put_byte
	call	dly
	banksel	PORTA
	bcf	PORTA,CE
	nop
	bsf	PORTA,CSN	;configuration enabled on falling edge of CSN
	return

;******************************************************************
;receive configuration
;******************************************************************
Rx_config:
	banksel	PORTA
	clrw
	movfw	PORTA		;all bits low
	movlw	0x38		;DATA1, DR1 output
	movfw	TRISA
	banksel	PORTA
	bcf	PORTA,CE	;set config mode (CE = 0. CS = 1)
	bsf	PORTA,CSN
	call	dly
	;send 24 bit configuration word 001000110100111000000101 (0x234E05) MS bit first
	movlw	0x23
	call	put_byte
	movlw	0x4E
	call	put_byte
	movlw	0x05
	call	put_byte
	banksel	PORTA
	bcf	PORTA,CE
	nop
	bcf	PORTA,CSN
	clrw
	movwf	PORTA
	movlw	0x3A		;DATA1 muse be input
	movwf	TRISA
	bcf	PORTA,CE
	nop
	bsf	PORTA,CSN
	return


;*****************************************************************************
;transmit data
;*****************************************************************************
Tx_data:
	banksel	PORTA
	bsf	PORTA,CE	;power up RF front end (CE = 1)
	call	dly
	movlw	0xE7		;RF address 11100111 (0xE7)
	call	put_byte	;clock in address
	movlw	0x11		;send four data bytes (0x11223344)
	call	put_byte
	movlw	0x22
	call	put_byte
	movlw	0x33
	call	put_byte
	movlw	0x44
	call	put_byte
	bcf	PORTA,CE	;start transmission (CE = 0)
	return


;****************************************************************************
;receive data
;****************************************************************************
Rx_data:
	banksel	PORTA
	bcf	PORTA,CE	;power down RF front end
	clrf	data_0		;zero buffers so that we can ensure that
	clrf	data_1		;correct date is being received
	clrf	data_2
	clrf	data_3
	call	get_byte	;receive four bytes and save in buffer
	movwf	data_0
	call	get_byte
	movwf	data_1
	call	get_byte
	movwf	data_2
	call	get_byte
	movwf	data_3
	bsf		PORTA,CE	;power up RF front end
	return

;***************************************************************************
;send byte to nRF24L01 (MS bit first)
;byte in  WREG
;***************************************************************************
put_byte:
	banksel	PORTA
	movwf	scrA	;save byte
	movlw	8	;initialise bit counter
	movwf	count
put_1:
	btfsc	scrA,7	;bit 7 = 0?
	goto	put_2	;no, jump
	bcf		PORTA,MOSI	;clear DATA
	nop
	bsf		PORTA,SCK	;clock it
	nop
	bcf		PORTA,SCK
	goto	put_3
put_2:
	bsf		PORTA,MOSI	;set DATA
	nop
	bsf		PORTA,SCK	;clock it
	nop
	bcf		PORTA,SCK
put_3:
	rlf		scrA,f		;left shift for next bit
	decfsz	count,f		;more bits?
	goto	put_1		;yes, loop back
	return				;no, return			


;***************************************************************************
;get byte from nRF24L01 (MS bit first) by clocking in data from MISO
;byte returned in WREG
;***************************************************************************
get_byte:
	banksel	PORTA
	movlw	8		;initialise bit counter
	movwf	count
get_1:
	btfsc	PORTA,MISO	;data = 1?
	goto	get_2		
	bcf		scrA,0		;no, clear MS bit
	goto	get_3
get_2:
	bsf		scrA,0		;Yes, set MS bit
get_3:
	bsf		PORTA,SCK
	nop
	bcf		PORTA,SCK
	rlf		scrA,f		;left shift for next bit
	decfsz	count,f		;more bits?
	goto	get_1		;no, loop back
	movfw	scrA		;return with byte in WREG
	return


;**************************************************************************
;delay routine
;**************************************************************************
dly:
	movlw	0xFF
	movwf	scrB
dly_1
	movlw	0xFF                        
	movwf	scrA                          
dly_2:	
	decfsz	scrA, F                    
	goto	dly_2
	decfsz	scrB,F
	goto	dly_1                          
	return
	

short_dly:
	movlw	0x0F                        
	movwf	scrA                          
short_1:	
	decfsz	scrA, F                    
	goto	dly_2
	decfsz	scrB,F
	return

	end

Leon

Thank you very much, Leon.

I have not used PIC MCU, and don’t quite understand the asm of PIC.

I am studying your code hard… :?

I think it was based on a C program for the PIC on the SFE web site (I prefer assembler to C on small PICs). You might find that easier to follow.

Leon

Very Strange :? … I just use JTAG to observe the STATUS value and find sometimes when I repower the RX board, STATUS value of the nrf24L01 on TX board might change to a unpredictable value. maybe EMC?

Haha the problem is solved! :smiley:

I used oscillograph to observe Voltage between VCC and GND of TX board and find that it has a low pulse when I repower the RX board. The power of TX board and RX board are both connected to output of AMS1117-3.3. After increase the capacitor connected between output of AMS1117-3.3 and GND, I find the low pulse decrease and the problem is solved.Hope it can help anyone who still in the same trouble as me. Thanks for all info and help in this forum. And many thanks for your kind help, Leon. I learn a lot from your code.

Hello,

I’m a beginner in this RF field. I’d like to read some AppNotes/reference designs on using nRF24 and PICs for low-power application.

Any reference is appreciated!

Cheers,

Mike