SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By rschoele
#23924
Hi everyone,

First off thanks everyone for sharing your knowledge. I'm pretty new at this. Also this is a repeat post - posted this same under 'Timing Issues' thread, but I figured I might here quicker with a new post

I'm using a 16F88 and its SPI interface to talk with the nRF24L01. I'm currently trying to re-write example code to work with my set up - I can see my data clock into the nRF24L01 with an analyzer, but I think I either have timing issues or I'm missing something because I can't get any comm going. I'm using a ccs picc compiler so it's a bit different than the CCX5(?) code examples I've found.

Right now I'm just trying to mimick the example and have basic shockburst TX and receive a payload on the other end. Once I get basics working then I'll work towards using the more advanced features and cleaning the code up. For now I'm breaking up all my instruction calls.

here's my TX and RX code - if anyone sees an issue please let me know. in the meantime I'll keep grinding. thanks

A question: Is there potential issues with using SPI? like timing, etc? I notice a lot of code using a bit-banging format and I'm wondering if there is an advantage of one over the other?

My TX code:
Code: Select all
#include<16F88.h>

#fuses INTRC_IO,NOWDT,NOPUT,MCLR,NOPROTECT,NOBROWNOUT,NOLVP,NOFCMEN,NOIESO
#use delay(clock=4000000)
#use standard_io(A)
#use standard_io(B)

/********************************START PIC16F88 Defines***********************************************/

// Control and SPI Pin defines ////////////////////////////////////////
#define CE		PIN_B5		// output Chip enable to nRF24L01 CE PIN_1
#define CSN		PIN_B3		// output Chip Select to nRF24L01 CSN PIN_2
#define SCK		PIN_B4		// serial clock output to nRF24L01 SCK PIN_3
#define MOSI	PIN_B2		// serial data out to nRF24L01 MOSI PIN_4 
#define MISO	PIN_B1		// serial data in from nRF24L01 MISO PIN_5
#define IRQ		PIN_B0		// input valid TX/RX from nRF24L01 IRQ PIN_6

// LED indicator Pins
#define LED0	PIN_A0
#define LED1	PIN_A1
#define LED2	PIN_A2

/********************************END PIC16F88 Defines*************************************************/
unsigned int cmd, data, j;

void spi_write1(int a){
		delay_us(10);
		spi_write(a);
		delay_us(10);
}

// Configure transmitter
void TX_Mode(){

output_low(CE);

output_low(CSN);
cmd = 0x20;	// write register, CONFIG
data = 0x38; //ptx, crc enable, mask a couple ints
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x24; // write register, setup_retr
data = 0x00;	// setup_retr = off
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x23; // write register, setup_aw
data = 0x03;	// address width = 5
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x26; // write register, RF_SETUP
data = 0x0F;	// data rate =2Mbps,0dBm,LNA gain
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x25; // write register, RF_CH
data = 0x02;	// default ch 2
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x30; // write register, TX address
data = 0xE7;	// set address E7E7E7E7E7
	spi_write(cmd);
	for(j=0;j<5;j++){
		spi_write1(data);
	}
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x21; // write register, en_aa
data = 0x00;	// disable auto-act in RX mode
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);
}

// Transmit data
void TX_Data(){

output_low(CSN);
cmd = 0x27; // write register, STATUS
data = 0x7E;	// clear previous ints
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x20; // write register, CONFIG
data = 0x3A;	// power up = 1
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0xE1; // flush_tx
	spi_write1(cmd);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0xA0; // write tx_payload
data = 0x34;	// 4 byte payload
	spi_write1(cmd);
	spi_write1(data);
data = 0x33;	// 4 byte payload
	spi_write1(data);
data = 0x32;	// 4 byte payload
	spi_write1(data);
data = 0x31;	// 4 byte payload
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_high(CE);
delay_us(20);
output_low(CE);
}


/********************************TX/RX IRQ Interrupt Acknowledgement********************************/

//Main
void main(){
setup_oscillator(OSC_4MHZ|OSC_INTRC);
setup_adc_ports(NO_ANALOGS);	// Set PortA Digital IO
setup_adc(ADC_OFF);				// Turn off ADC
setup_ccp1(CCP_OFF);			// Turn off CCP - will disrupt output writes on PIN_B3 if on
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64);

// set up IRQ (PIN_B0) interrupt for TX/RX notification
//enable_interrupts(INT_EXT);
//ext_int_edge(H_TO_L);
//enable_interrupts(GLOBAL);
//output_low(CE);		// set CE low to disable transmission
output_b(0b00001000);
output_low(LED0 | LED1 | LED2);		// set LEDs Low

delay_ms(2);
output_high(LED0);
TX_Mode();
output_low(LED0);

	while(1){

		TX_Data();
		output_high(LED2);
		delay_ms(10);
		output_low(LED2);
		delay_ms(500);
	}

}
My RX code:
Code: Select all
/* RF weapon track test code - R.Schoelerman 11/06
SPI interface between PIC16F88 and nRF24L01

nRF24L01 IO:
	Chip Select				RB3
	Chip Enable				RB5
	IRQ						RB6

SPI Control Pins:
	Serial Data Out (SDO)	RB2
	Serial Data In (SDI)	RB1
	Serial Clock (SCK)		RB4
*/
#include<16F88.h>

#fuses INTRC_IO,NOWDT,NOPUT,MCLR,NOPROTECT,NOBROWNOUT,NOLVP,NOFCMEN,NOIESO
#use delay(clock=4000000)
#use standard_io(A)
#use standard_io(B)

/********************************START PIC16F88 Defines***********************************************/

// Control and SPI Pin defines ////////////////////////////////////////
#define CE		PIN_B5		// output Chip enable to nRF24L01 CE PIN_1
#define CSN		PIN_B3		// output Chip Select to nRF24L01 CSN PIN_2
#define SCK		PIN_B4		// serial clock output to nRF24L01 SCK PIN_3
#define MOSI	PIN_B2		// serial data out to nRF24L01 MOSI PIN_4 
#define MISO	PIN_B1		// serial data in from nRF24L01 MISO PIN_5
#define IRQ		PIN_B0		// input valid TX/RX from nRF24L01 IRQ PIN_6

// LED indicator Pins
#define LED0	PIN_A0
#define LED1	PIN_A1
#define LED2	PIN_A2

/********************************END PIC16F88 Defines*************************************************/
unsigned int data, cmd, j;

void spi_write1(int a){
		delay_us(10);
		spi_write(a);
		delay_us(10);
}
void spi_read1(int a){
		delay_us(10);
		data = spi_read(a);
		delay_us(10);
}
// Configure receiver
void RX_Mode(void){
int data, cmd, j;

output_low(CE);

output_low(CSN);
cmd = 0x20;	// write register, CONFIG
data = 0x39; //prx, crc enable, mask a couple ints
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x21; // write register, en_aa
data = 0x00;	// dissable auto ack
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x23; // write register, setup_aw
data = 0x03;	// address width = 5
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x26; // write register, RF_SETUP
data = 0x0F;	// data rate =2Mbps,0dBm,LNA gain
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x31; // write register, tx address
data = 0x04;	// 4 byte payload
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x25; // write register, rf channel
data = 0x02;	// channel 2
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x30; // write register, RX address
data = 0xE7;	// set address E7E7E7E7E7
	spi_write1(cmd);
	for(j=0;j<5;j++){
		spi_write1(data);
	}
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x20; // write register, config
data = 0x3B;	// power up = 1
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);
output_high(CE);
delay_us(20);
}

// reset all ints
void reset_RX(void){
int data, cmd;

output_low(CSN);
cmd = 0x61; // read rx payload
	//spi_write1(cmd);
	spi_read1(cmd);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0xE2; // flush rx
data = 0x3A;	// power up = 1
	spi_write1(cmd);
output_high(CSN);
delay_us(20);

output_low(CSN);
cmd = 0x27; // write register STATUS
data = 0x40;	// 
	spi_write1(cmd);
	spi_write1(data);
output_high(CSN);

}


/********************************TX/RX IRQ Interrupt Acknowledgement********************************/

//Main
void main(){
setup_oscillator(OSC_4MHZ|OSC_INTRC);
setup_adc_ports(NO_ANALOGS);	// Set PortA Digital IO
setup_adc(ADC_OFF);				// Turn off ADC
setup_ccp1(CCP_OFF);			// Turn off CCP - will disrupt output writes on PIN_B3 if on
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64);

// set up IRQ (PIN_B0) interrupt for TX/RX notification
//enable_interrupts(INT_EXT);
//ext_int_edge(H_TO_L);
//enable_interrupts(GLOBAL);
//output_low(CE);		// set CE low to disable transmission
output_b(0b00001000);
output_low(LED0 | LED1 | LED2);		// set LEDs Low

delay_ms(2);

output_high(LED0);
RX_mode();
output_low(LED0);

while(1){
int x;
		if(IRQ == 0){
			for(x=0;x<5;x++){
				output_high(LED2);
				delay_ms(100);
				output_low(LED2);
				delay_ms(100);
			}
			delay_ms(200);
			reset_RX();
		}
}

}
By brennen
#23986
Have you looked at my C code for interfacing these modules? You can check them out at nrf24l01.h and nrf24l01.c. In order to use my code, you have to write some functions for yourself that match my prototypes, so for most people just looking at the code to see how I got my timing and stuff works for them.
By brennen
#23987
As a secondary post, all of the timing information is in Figure 10 and Table 9/10 in the datasheet of the 24L01 (page 21). You have to follow this to a T or the unit generally will not like you. Are you getting back the status byte when you send data to the 24L01? You could try to send the NOP instruction by bit-banging (it is 0xFF or 11111111 in binary) and watch the output of the 24L01 to see if it sends you anything. You can actually bit-bang the unit very slowly just to ensure that you have a working module.
By rschoele
#23989
Hi Brennen,

I did get it to work somewhat. The problem was using the built in SPI, I naively assumed that there wouldn't be any issues there. Turns out when I did a bit-banging set up it works and I see the status come back on the MISO.

Yes I have your code and I have it compiled for the PIC, but I wanted to work from a basic level first to get a better understanding of how the nRF24L01 works. Which turns out to be the best option because I'll now be able to write a better bit-banging spi to work with your code.

My problem now is my receiver acknowledges the first receive, the IRQ resets, but then it doesn't receive a second time unless I cycle the power. But now that I know it works on some level I feel confident that I can fix that, plus there has already been a number of posts on this device to help me out.

thanks
Ryan
By brennen
#23994
Ah, yes. The other topic you posted in (nRF24L01 timing issues, I think it's called) has a discussion about this. mchang and I had different ways of getting around this, but both seemed to work. I personally believe it is a silicon error, but another user posted in that forum and was able to get his working without having to do a workaround. IIRC, I cleared the FIFO after reading out all the data and this allowed the 24L01 to start working again.
By rschoele
#24011
yup - exactly - I went back and read the posts between you and mchang and when I made the changes to CE it worked fine.

Again thanks to you and the others - this is a great resource!

rschoele
By joni
#30499
Hello rschoele: Could you post your code with bit-banging? I'm surprised about how you did it.
Thanks a lot!
By rschoele
#30518
I've been developing spi mode since these posts - once you get your mind wrap around this transceiver it's pretty smooth and easy to operate using autoack and all the datapipes. If your MCU has spi capability then I would suggest that route.

This is the code I started with, but I can't guarantee that it works - it might not have been working all that great originally and I've never debugged it or tested it further after I got SPI mode to work properly. So have at it, I posted RX code first and TX code after. Also note that this code does not take advantage of interrupts, it constantly polls in the RX mode.

best,
rschoele

RX code
Code: Select all
/*
Basic RX code for nRF24L01 interfaced to PIC16LF88
No auto-ack enabled, 4byte payload
This is not enhanced shockburst - this code doesn't take advantage of nRF24L01 advanced features.
COMM with nRF24L01 using bit-banging scheme
NOT FULLY TEST - NOT GUARANTEED TO WORK
*/

#include<16F88.h>

#fuses INTRC_IO,NOWDT,NOPUT,MCLR,NOPROTECT,NOBROWNOUT,NOLVP,NOFCMEN,NOIESO
#use delay(clock=8000000)
#use standard_io(A)
#use standard_io(B)

/********************************START PIC16F88 Defines***********************************************/
 
// Control and SPI Pin defines ////////////////////////////////////////
#define CE		PIN_B5		// output Chip enable to nRF24L01 CE PIN_1
#define CSN		PIN_B3		// output Chip Select to nRF24L01 CSN PIN_2
#define SCK		PIN_B4		// serial clock output to nRF24L01 SCK PIN_3
#define MOSI	PIN_B2		// serial data out to nRF24L01 MOSI PIN_4 
#define MISO	PIN_B1		// serial data in from nRF24L01 MISO PIN_5
#define IRQ		PIN_B0		// input valid TX/RX from nRF24L01 IRQ PIN_6

// LED indicator Pins
#define LED0	PIN_A0
#define LED1	PIN_A1
#define LED2	PIN_A2

/********************************END PIC16F88 Defines*************************************************/

#define	RX_PLOAD_WIDTH	4
// Buffer to hold data from 'SPI_Read_Buf()' function
extern BYTE SPI_Buffer[32];
BYTE RX_PAYLOAD[RX_PLOAD_WIDTH] = {0x34,0x33,0x32,0x31};

void putByte(byte b) {  //MSB bit first
	unsigned int i;
   	unsigned int p = 7;
	output_low(SCK);
   	for(i=0 ; i < 8 ; i++) {
    	if( bit_test(b,p--) ) {
        	output_high(MOSI);
      	}else{
        	output_low(MOSI);
      	}
      	output_high(SCK);
		delay_us(10);
      	output_low(SCK);
      	delay_us(1);
   }
}
BYTE getByte() {  //MSB bit first
   unsigned int i , b = 0;
   unsigned p = 7;
	output_low(SCK);
   	for(i=0 ; i < 8 ; i++) {
   	 	if( input(MISO) ) {
      	   bit_set(b,p--);
      	}else{
       	  bit_clear(b,p--);
     	 }
      	output_high(SCK);
		delay_us(10);
      	output_low(SCK);
      	delay_us(1);
  	}
   return b;
}
// Read 'bytes' #of from register 'reg' - use to read RX payload, RX/TX address
BYTE SPI_Read_Buf(byte reg, byte *pBuf, byte numbytes){
byte state, byte_ctr;
	putByte(reg);
	for(byte_ctr=0; byte_ctr < numbytes; byte_ctr++){
		pBuf[byte_ctr] = getByte();
	}
}

// Configure receiver
void RX_Mode(void){
int data, cmd, j;

output_low(CE);

output_low(CSN);
cmd = 0x20;	// write register, CONFIG
data = 0x39; //prx, crc enable, mask a couple ints
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x21; // write register, en_aa
data = 0x00;	// dissable auto ack
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x23; // write register, setup_aw
data = 0x03;	// address width = 5
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x26; // write register, RF_SETUP
data = 0x07;	// data rate =1Mbps,0dBm,LNA gain
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x31; // write register, number of bytes RX_PW_P0
data = 0x04;	// 4 byte payload
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x25; // write register, rf channel
data = 0x02;	// channel 2
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x30; // write register, RX address
data = 0xE7;	// set address E7E7E7E7E7
	putByte(cmd);
	for(j=0;j<5;j++){
		putByte(data);
	}
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x20; // write register, config
data = 0x3B;	// power up = 1
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);
output_high(CE);
delay_us(1);
}

// reset all ints
void reset_RX(void){
int data, cmd;

output_low(CE);
output_low(CSN);
cmd = 0x61; // read rx payload
	//putByte(cmd);
	SPI_Read_Buf(cmd, SPI_Buffer, 5);
output_high(CSN);
delay_us(1);

if(*SPI_Buffer == *RX_PAYLOAD){
//if((SPI_Buffer[0] == RX_PAYLOAD[0])&&(SPI_Buffer[3] == RX_PAYLOAD[3])){
	output_high(LED1);
	delay_ms(250);
}

output_low(CSN);
cmd = 0x27; // write register STATUS
data = 0x40;	// clear RX_DR
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0xE2; // flush rx
	putByte(cmd);
output_high(CSN);
delay_us(1);

output_high(CE);
}


/********************************TX/RX IRQ Interrupt Acknowledgement********************************/

//Main
void main(){
int x;
setup_oscillator(OSC_8MHZ|OSC_INTRC);
setup_adc_ports(NO_ANALOGS);	// Set PortA Digital IO
setup_adc(ADC_OFF);				// Turn off ADC
setup_ccp1(CCP_OFF);			// Turn off CCP - will disrupt output writes on PIN_B3 if on

*SPI_Buffer = 0;
output_low(LED0 | LED1 | LED2);
output_high(CE);
delay_ms(2);

output_high(LED0);
RX_mode();
output_low(LED0);
delay_us(200);

	while(1){
	output_low(LED1);
		if(!input(IRQ)){
			for(x=0;x<3;x++){
				output_high(LED2);
				delay_ms(100);
				output_low(LED2);
				delay_ms(100);
			}
			delay_ms(200);
			reset_RX();
		}
	delay_ms(100);
	}

}
TX code
Code: Select all
/*
Basic TX code for nRF24L01 interfaced to PIC16LF88
No auto-ack enabled, 4byte payload
This code doesn't take advantage of nRF24L01 advanced features.

NOT FULLY TEST - NOT GUARANTEED TO WORK
*/

#include<16F88.h>
//#include<nRF24L01_Define.h>

#fuses INTRC_IO,NOWDT,NOPUT,MCLR,NOPROTECT,NOBROWNOUT,NOLVP,NOFCMEN,NOIESO
#use delay(clock=8000000)
#use standard_io(A)
#use standard_io(B)

/********************************START PIC16F88 Defines***********************************************/

// Control and SPI Pin defines ////////////////////////////////////////
#define CE		PIN_B5		// output Chip enable to nRF24L01 CE PIN_1
#define CSN		PIN_B3		// output Chip Select to nRF24L01 CSN PIN_2
#define SCK		PIN_B4		// serial clock output to nRF24L01 SCK PIN_3
#define MOSI	PIN_B2		// serial data out to nRF24L01 MOSI PIN_4 
#define MISO	PIN_B1		// serial data in from nRF24L01 MISO PIN_5
#define IRQ		PIN_B0		// input valid TX/RX from nRF24L01 IRQ PIN_6

// LED indicator Pins
#define LED0	PIN_A0
#define LED1	PIN_A1
#define LED2	PIN_A2

/********************************END PIC16F88 Defines*************************************************/
#define	TX_PLOAD_WIDTH	4
// Buffer to hold data from 'SPI_Read_Buf()' function
extern BYTE SPI_Buffer[32];
BYTE TX_PAYLOAD[TX_PLOAD_WIDTH] = {0x34,0x33,0x32,0x31};

// write one byte, MSBit first
void putByte( byte b ) {
	unsigned int i;
   	unsigned int p = 7;
	output_low(SCK);
   	for(i=0 ; i < 8 ; i++) {
    	if( bit_test(b,p--) ) {
        	output_high(MOSI);
      	}else{
        	output_low(MOSI);
      	}
      	output_high(SCK);
		delay_us(10);
      	output_low(SCK);
      	delay_us(1);
   }
}
byte getByte() {  //MSB bit first
   unsigned int i , b = 0;
   unsigned p = 7;
	output_low(SCK);
   	for(i=0 ; i < 8 ; i++) {
   	 	if( input(MISO) ) {
      	   bit_set(b,p--);
      	}else{
       	  bit_clear(b,p--);
     	 }
      	output_high(SCK);
		delay_us(10);
      	output_low(SCK);
      	delay_us(1);
  	}
   return b;
}
// Read 'bytes' #of from register 'reg' - use to read RX payload, RX/TX address
BYTE SPI_Write_Buf(byte reg, byte *pBuf, byte numbytes){
byte byte_ctr;
	putByte(reg);
	for(byte_ctr=0; byte_ctr < numbytes; byte_ctr++){
		putByte(pBuf[byte_ctr]);
	}
}
// Read 'bytes' #of from register 'reg' - use to read RX payload, RX/TX address
BYTE SPI_Read_Buf(byte reg, byte *pBuf, byte numbytes){
byte state, byte_ctr;
	putByte(reg);
	for(byte_ctr=0; byte_ctr < numbytes; byte_ctr++){
		pBuf[byte_ctr] = getByte();
	}
}
// Configure transmitter
void TX_Mode(){
unsigned int j, cmd, data, data2;
data2 = 0;

output_low(CE);

output_low(CSN);
cmd = 0x20;	// write register, CONFIG
data = 0x38; //ptx, crc enable, mask a couple ints
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x24; // write register, setup_retr
data = 0x00;	// setup_retr = off
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x23; // write register, setup_aw
data = 0x03;	// address width = 5
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x26; // write register, RF_SETUP
data = 0x07;	// data rate =1Mbps,0dBm,LNA gain
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x25; // write register, RF_CH
data = 0x02;	// default ch 2
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x30; // write register, TX address
data = 0xE7;	// set address E7E7E7E7E7
	putByte(cmd);
	for(j=0;j<5;j++){
		putByte(data);
	}
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x21; // write register, en_aa
data = 0x00;	// disable auto-act in RX mode
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);
}

// Transmit data
void TX_Data(){
unsigned int cmd, data;

output_low(CSN);
cmd = 0x27; // write register, STATUS
data = 0x7E;	// clear previous ints
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0x20; // write register, CONFIG
data = 0x3A;	// power up = 1
	putByte(cmd);
	putByte(data);
output_high(CSN);
delay_us(1);

output_low(CSN);
cmd = 0xE1; // flush_tx
	putByte(cmd);
output_high(CSN);
delay_us(1);

output_low(CSN);
SPI_Write_Buf(0xA0, TX_PAYLOAD, TX_PLOAD_WIDTH);
output_high(CSN);
delay_us(1);

output_high(CE);
delay_us(20);
output_low(CE);
}


/********************************TX/RX IRQ Interrupt Acknowledgement********************************/

//Main
void main(){
setup_oscillator(OSC_8MHZ|OSC_INTRC);
setup_adc_ports(NO_ANALOGS);	// Set PortA Digital IO
setup_adc(ADC_OFF);				// Turn off ADC
setup_ccp1(CCP_OFF);			// Turn off CCP

output_low(LED0 | LED1 | LED2);		// set LEDs Low

	delay_ms(2);
	output_high(LED0);
	delay_ms(250);
	TX_Mode();
	output_low(LED0);
	delay_ms(500);
	while(1){

		TX_Data();
		output_high(LED2);
		delay_ms(10);
		output_low(LED2);
		delay_ms(2000);
	}

}
By joni
#30671
Thanks a lot! Yes it works with bit-banging, but how did you change your program with SPI, that it works now? Firstly you said it didn't work. What is different now to your first code (you posted it at first)? Thank you for helping me.
Best
Joni
By rschoele
#30686
if your using spi with a pic it handles the clocking for you as well as timing.
For example in putByte() your bit testing the MOSI pin in the for loop 8 times to send one full byte - between each bit set you put the clock high, then low so it shifts the bit out on the falling edge of your clock pulse.

If you look at the timing diagram in the nRF24L01 datasheet you'll see that as you clock in data you'll get a status byte back, to read that status byte simulataneously using the bit banging method gets tricky (it can be done but using SPI it's done for you already) - with bit banging you have a separate call getByte() to read bytes. With SPI configured you get rid of both putByte and getByte and have:
Code: Select all
BYTE SPI_RW(byte b) {
	b = spi_read(b);
	delay_us(1);
	return b;
}
the spi_read function sends out your byte of data already timed properly with the clock (notice no high/low calls to the SCK pin - the clock is configured in the setup). Also it clocks in the status byte back and returns it as 'b' to do with as you wish.

In a nutshell it alleviates any potential clocking issues and reduces the amount of code. The setup configuration would look like this.
Code: Select all
setup_adc_ports(NO_ANALOGS);	// Set PortA Digital IO
setup_adc(ADC_OFF);		// Turn off ADC
setup_ccp1(CCP_OFF);	// Turn off CCP, disrupts SPI
setup_ccp2(CCP_OFF);
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);

//configure the ports based on your setup - 3 portb pins are used by SPI for SDO,SDI, and SCK and have to be set.
set_tris_c(0b10010000); // Configure ports - with spi ports have
set_tris_b(0b00000001);//to be set - you can't use fast_io
I should mention that this code was written using the CCS PICC compiler
HINT: if you go to the Nordic website and download the firmware for their evaluation boards - in it is sample code for and MCU to control the nRF24L01 - it's very easy to translate over to a PIC with spi configured.

best
Ryan
By joni
#30721
Thank you very much!! It works now!
Best Joni