I have downloaded from Mikroelektronika-libstock the project of "Allen Mulvey", thanks for showing how to setup this in easy way using a LCD 16x2. But that project is for the PIC16.
Since I bought the "Easy24-33 v6 board" and "EasyPIC Fusion v7 board" and their respective MiKROC Compilers I have been working with PIC24F16KA102 and PIC32MX795F512L; where you are going to find that main difference are configuration of the registers and some changes of the code.
For instance:
Meanwhile in PIC16 or mikroC Pro for PIC you set the pins:
sbit Irq_pin at PORTB.B0; sfr;
in mikroC Pro for dsPIC you set:
sbit Irq_pin at LATB14_bit; sfr;
(Pin configuration of PIC16 according to original project of Allen, pin configuration for PIC24F16KA102, selected by me) [project of PIC24 using HS+PLL, primary HS oscillator mode selected, and project set to 32MHz]
Another piece of code:
CMCON = 7; // Comparators off in PIC16
CM1CONbits.CON = 0; // Comparator 1 off in PIC24
//CM1CONbits.CREF = x; // not clear in data sheet
//CM1CONbits.CCH = xx; // not clear in data sheet
CM2CONbits.CON = 0; // Comparator 2 off in PIC24
//CM2CONbits.CREF = x; // not clear in data sheet
//CM2CONbits.CCH = xx; // not clear in data sheet
ADCON1 = 0x04; // digital not analog in PIC16
AD1PCFG = 0xFFFF; // digital not analog in PIC24
Those 3 parts were the only ones that I found in error after compile the project. After change those I got “Project Linked Successfully” finished without any error.
However when I test in the circuit, there is not communication between the two nRF24L01 modules.
There is an interesting phrase of Allen, where he says:
“June 30, 2014
The code as posted seems to work well at oscillator speeds up to 20 MHZ. Today I attempted to run it on a PIC18F46K22 at 32 MHX (8 MHZ x 4). I had to use the advanced SPI initialization to accomodate the faster clock. This is what I used: SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
“
where if I change to:
//SPI1_Init();
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
I got erros, because SPI advance options change to MikroC DsPIC.
So, my set was:
SPI1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_6, _SPI_PRESCALE_PRI_4, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_IDLE_2_ACTIVE);
After testing, I only got the display of the LCD without the message of testing “Test Message”.
According to your experience, what could be the problem?,
Do yo see any error in the code??
Code: Select all
/*================================================================================
*
* nRF24L01+ using no libraries
* PIC16F877A migration to PIC24F16KA102
*
* Allen Mulvey May 2014 original file modified
*
* Pull up resistors on PORTC pins 1-5 <= apparently not necessary
*
================================================================================*/
#define TX_mode // define TX_mode or RX_mode
//#define chn 83
#include "nRF24L01.h"
const char test[] = "Hi nRF24L01";
// Pipe Addresses
// adr0 should be unique
// adr1 through adr5 must differ only in the lowest significant byte
// Bytes are arranged lowest to highest
const char adr0[] = {0x78,0x78,0x78,0x78,0x78}; // LSB first
const char adr1[] = {0xf1,0xb4,0xb5,0xb6,0xb3};
const char adr2[] = {0xb3,0xb4,0xb5,0xb6,0xb3};
const char adr3[] = {0x83,0xb4,0xb5,0xb6,0xb3};
const char adr4[] = {0xcf,0xb4,0xb5,0xb6,0xb3};
const char adr5[] = {0x75,0xb4,0xb5,0xb6,0xb3};
char Data_In[21], Data_Out[21], stat;
short dataLength = 20;
// You can change these pins as long as your microcontroller supports SPI on the required pins
sbit Irq_pin at LATB14_bit; sfr;
//sbit Mosi_pin at LATB13_bit; sfr;
sbit Ce_pin at LATB12_bit; sfr;
//sbit Sclk_pin at LATB11_bit; sfr;
sbit Csn_pin at LATB9_bit; sfr;
//sbit Miso_pin at LATB10_bit; sfr;
sbit Irq_tris at TRISB14_bit; sfr;
//sbit Mosi_tris at TRISB13_bit; sfr;
sbit Ce_tris at TRISB12_bit; sfr;
//sbit Sclk_tris at TRISB11_bit; sfr;
sbit Csn_tris at TRISB9_bit; sfr;
//sbit Miso_tris at TRISB10_bit; sfr;
// LCD module connections
sbit LCD_RS at LATA0_bit;
sbit LCD_EN at LATA1_bit;
sbit LCD_D4 at LATB3_bit;
sbit LCD_D5 at LATB4_bit;
sbit LCD_D6 at LATA4_bit;
sbit LCD_D7 at LATB5_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB3_bit;
sbit LCD_D5_Direction at TRISB4_bit;
sbit LCD_D6_Direction at TRISA4_bit;
sbit LCD_D7_Direction at TRISB5_bit;
// End LCD module connections
// I use a procedure for any delay that is used more than once
void Comm_Delay() {Delay_us(10);} // You can experiment with this delay
void Delay_10() {Delay_ms(10);}
void Delay_100() {Delay_ms(100);}
void Delay_500() {Delay_ms(500);}
void Clear_Data(char dat[]){
char i;
for(i=0;i<dataLength;i++)dat[i] = ' ';
}
void toggleCSN(){
Csn_pin = 1;
Delay_us(20); // You can experiment with this delay
Csn_pin = 0;
Comm_Delay();
}
char Get_Status(){
char s;
Ce_pin = 0;
toggleCSN();
SPI1_Write(STATUS);
Comm_Delay();
s = SPI1_Read(NOP);
Comm_Delay();
Csn_pin = 1;
return s;
}
char *getConst(char dest[], const char source[]){
int i = 0;
while (source[i]) // while (source[i] != '\0')
{dest[i] = source[i]; i++;}
dest[i] = '\0';
return dest;
}
char Get_FIFO_Flags(){
char s;
Ce_pin = 0;
toggleCSN();
SPI1_Write(FIFO_STATUS);
Comm_Delay();
s = SPI1_Read(NOP);
Comm_Delay();
Csn_pin = 1;
return s;
}
void makeMsg(){ // Put your data in here
Clear_Data(Data_Out);
getConst(Data_Out, test);
}
char readBuffer(){
char i, s;
Ce_pin = 0;
Clear_Data(Data_In);
s = Get_FIFO_Flags();
if((s & 2) != 0){
toggleCSN();
SPI1_Write(R_RX_PAYLOAD);
for(i=0; i < dataLength; i++){Comm_Delay(); Data_In[i] = SPI1_Read(0);}
Comm_Delay();
}
Csn_pin = 1;
Ce_pin = 1;
return s;
}
void sendBuffer(){
char i, j;
do{
toggleCSN();
SPI1_Write(STATUS | W_REGISTER);
Comm_Delay();
SPI1_Write(0xff); //clear flags
Comm_Delay();
toggleCSN();
SPI1_Write(FLUSH_TX);
Comm_Delay();
toggleCSN();
SPI1_Write(W_TX_PAYLOAD);
for(i = 0; i < dataLength; i++) {Comm_Delay(); SPI1_Write(Data_Out[i]);}
Comm_Delay();
Csn_pin = 1;
Ce_pin = 1;
Delay_10();
j = (Get_Status() & 0x20); // keep trying until ack is received
}while(j==0);
}
char init_Radio(){
char i;
Ce_pin = 0; // must be in standby or power down to write
Comm_Delay();
toggleCSN();
SPI1_Write(CONFIG | W_REGISTER);
Comm_Delay();
#ifdef RX_mode
SPI1_Write(PRIM_RX + PWR_UP + CRCO + EN_CRC); // Receiver
toggleCSN();
SPI1_Write(EN_AA | W_REGISTER);
Comm_Delay();
SPI1_Write(ENAA_P0 + ENAA_P1 + ENAA_P2 + ENAA_P3 + ENAA_P4 + ENAA_P5);
Comm_Delay();
toggleCSN();
SPI1_Write(EN_RXADDR | W_REGISTER);
Comm_Delay();
SPI1_Write(ERX_P0 + ERX_P1 + ERX_P2 + ERX_P3 + ERX_P4 + ERX_P5);
Comm_Delay();
#endif
#ifdef TX_mode
SPI1_Write(PWR_UP + CRCO + EN_CRC); // Transmitter
Comm_Delay();
toggleCSN();
SPI1_Write(EN_AA | W_REGISTER);
Comm_Delay();
SPI1_Write(ENAA_P0);
Comm_Delay();
toggleCSN();
SPI1_Write(EN_RXADDR | W_REGISTER);
Comm_Delay();
SPI1_Write(ERX_P0);
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P0 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr0[i]);} // This is the pipe in use by this transmitter
Comm_Delay();
// The addresses above and below must be the same
toggleCSN(); // Choose any of the 6 addresses used by the receiver
SPI1_Write(TX_ADDR | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr0[i]);} // This is the pipe in use by this transmitter
Comm_Delay();
#endif
toggleCSN();
SPI1_Write(SETUP_AW | W_REGISTER);
Comm_Delay();
SPI1_Write(AW5);
Comm_Delay();
toggleCSN();
SPI1_Write(SETUP_RETR | W_REGISTER);
Comm_Delay();
SPI1_Write(0xfaf);
Comm_Delay();
toggleCSN();
SPI1_Write(RF_CH | W_REGISTER);
Comm_Delay();
SPI1_Write(83); // Set your channel here. Obviously it must be the same for TX and RX.
Comm_Delay();
toggleCSN();
SPI1_Write(RF_SETUP | W_REGISTER);
Comm_Delay();
SPI1_Write(RF_PWR + LNA_HCURR);
Comm_Delay();
#ifdef RX_mode
toggleCSN();
SPI1_Write(RX_ADDR_P0 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr0[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P1 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr1[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P2 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr2[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P3 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr3[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P4 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr4[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_ADDR_P5 | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr5[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(TX_ADDR | W_REGISTER);
for(i=0;i<5;i++){Comm_Delay(); SPI1_Write(adr0[i]);}
Comm_Delay();
toggleCSN();
SPI1_Write(RX_PW_P1 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
toggleCSN();
SPI1_Write(RX_PW_P2 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
toggleCSN();
SPI1_Write(RX_PW_P3 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
toggleCSN();
SPI1_Write(RX_PW_P4 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
toggleCSN();
SPI1_Write(RX_PW_P5 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
#endif
toggleCSN();
SPI1_Write(RX_PW_P0 | W_REGISTER);
Comm_Delay();
SPI1_Write(dataLength);
Comm_Delay();
Csn_pin = 1;
i = Get_Status();
return i;
}
// =============================================================================
// =============================================================================
void main(){
char txt[5], dat1;
AD1PCFG = 0xFFFF; // digital not analog
CM1CONbits.CON = 0; // Comparators off
//CM1CONbits.CREF = ;
//CM1CONbits.CCH = ;
CM2CONbits.CON = 0; // Comparators off
//CM2CONbits.CREF = ;
//CM2CONbits.CCH = ;
//PORTA = 0;
//TRISA = 0; // outputs
Csn_tris = 0;
Csn_pin = 1;
Ce_tris = 0;
Ce_pin = 0; // 1 = listen or transmit
//SPI1_Init();
//SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); //config for PIC16
SPI1_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_6, _SPI_PRESCALE_PRI_4, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_IDLE_2_ACTIVE);
Delay_ms(200);
stat = init_Radio();
#ifdef TX_mode
Clear_Data(Data_Out);
#endif
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Out(1, 1, "nRF24L01+");
ByteToHex(stat, txt);
Lcd_Out(2, 1, txt);
Delay_500();
do {
dat1 = 0;
Lcd_Cmd(_LCD_CLEAR); // Clear display
dat1 = Get_Status();
ByteToHex(dat1, txt);
Delay_10();
Lcd_Out(1, 6, txt);
dat1 = Get_FIFO_Flags();
ByteToHex(dat1, txt);
Delay_10();
Lcd_Out(1, 11, txt);
#ifdef TX_mode
Lcd_Out(1, 1, "TX");
Lcd_Out(2, 1, Data_Out);
Delay_100();
makeMsg();
sendBuffer();
Delay_100();
#endif
#ifdef RX_mode
Ce_pin = 1;
Lcd_Out(1, 1, "RX");
dat1 = readBuffer();
ByteToHex(dat1, txt);
Delay_10();
Lcd_Out(1, 11, txt);
if((dat1 & 2) != 0) Lcd_Out(2, 1, Data_In);
Delay_500();
#endif
}while(1);
}