I am not sure if this is the best place to put this, but I’ve been trying to get this project up and running for weeks now and can’t even get the nRF24L01+ and PIC16F1829 to transmit any data, so anything would help. I’m trying to use the PIC16F1829 as the host through the nRF24L01+, to transmit data to another nRF connected to an Arduino Uno. Here is my code so far:
main.c
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disable)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#include <stdio.h>
#include <xc.h>
#include <pic16f1829.h>
#define _XTAL_FREQ 8000000
#include "nRF24L01.h"
int main ( void ) {
OSCCONbits.IRCF = 0b1110; // 8MHz
TRISAbits.TRISA2 = 1;
TRISAbits.TRISA3 = 1;
TRISAbits.TRISA4 = 1;
nRF_Init(TX_MODE, 0x40);
char bufferTX[32];
bufferTX[0] = '-';
while(1) {
if(PORTAbits.RA2 == 1) {
bufferTX[0] = 'A';
}
if(PORTAbits.RA3 == 1) {
bufferTX[0] = 'B';
}
if(PORTAbits.RA4 == 1) {
bufferTX[0] = 'C';
}
nRF_SendData(bufferTX);
}
return (0);
}
nRF24L01.c
#include "nRF24L01.h"
// This data type sets the address data pipe 0.
unsigned char ADDRESS_DATA_PIPE0[5] = {0x05,0x04,0x03,0x02,0x01};
void nRF_Init(char mode, char rf_channel) {
// SPI
// disable MSSP
SSP1CON1bits.SSPEN = 0;
// SDI1 set
TRISBbits.TRISB4 = 1; // configure RC4 as input
ANSELBbits.ANSB4 = 0; // enable digital input buffer on RC4
// SS1 set
TRISCbits.TRISC6 = 0;
// SDO1 cleared
ANSELCbits.ANSC7 = 0;
TRISCbits.TRISC7 = 0;
// SCK1 cleared
TRISBbits.TRISB6 = 0;
TRISBbits.TRISB6 = 0;
// SPI mode 0
SSP1CON1bits.CKP = 0; // Idle state for clock is a low level
SSP1STATbits.CKE = 1; // Transmit occurs on transition from active to Idle clock state
SSP1STATbits.SMP = 1; // Input data sampled at end of data output time (took me 5 friggin' hours)
SSP1CON1bits.SSPM = 0b0001; //0001 = SPI Master mode, clock = FOSC/16
SSP1CON1bits.SSPEN = 1; // enable MSSP1
//nRF
CSN_DDR_Low();
CE_DDR_Low();
CSN_High();
CE_Low();
__delay_ms(100);
nRF_WriteRegister(CONFIG, 0x0E); // Power Up, CRC Enable, CRC 2 byte
__delay_ms(10);
nRF_WriteRegister(EN_AA, 0x01); // Enable RX Address (data pipe 0)
nRF_WriteRegister(SETUP_AW, 0x03); // RX/TX Address field width is 5 bytes
nRF_WriteRegister(SETUP_RETR, 0x00); // Auto Retransmit Delay = 250us
// Sets the frequency channel nRF24L01+ operates on
nRF_WriteRegister(RF_CH, rf_channel);
nRF_WriteRegister(RF_SETUP, 0x06); // RF Data Rate = 1Mbs, RF output power in TX mode = 0dBm
nRF_WriteBuffer(W_REGISTER | RX_ADDR_P0, ADDRESS_DATA_PIPE0, 5);
nRF_WriteBuffer(W_REGISTER | TX_ADDR, ADDRESS_DATA_PIPE0, 5);
nRF_WriteRegister(RX_PW_P0, PAYLOAD_BYTES);
__delay_ms(100);
nRF_SetMode(mode);
__delay_ms(100);
}
void nRF_WriteRegister(char mnemonic, char value) {
CSN_Low(); // Enable chip
SPI_Write(W_REGISTER | mnemonic);
SPI_Write(value);
CSN_High(); // Disable chip
}
void SPI_Write(char data) {
SSP1BUF = data; // Copy data in SSBUF to transmit
while(!SSPSTATbits.BF); // Wait for complete 1 byte transmission
data = SSP1BUF; // Clear SSP2IF flag
}
void nRF_WriteBuffer(char data, char* buffer, char bytes) {
CSN_Low();
SPI_Write(data);
for(char i = 0; i < bytes; i++) {
SPI_Write(*buffer);
buffer++;
}
CSN_High();
}
void nRF_SetMode(char mode) {
nRF_Flush(); // Clear RX and TX FIFO
nRF_WriteRegister(STATUS_N, 0x70); // Clear STATUS
if(mode) {
nRF_WriteRegister(CONFIG, 0x0F); // RX Control
CE_High(); // RX Mode
} else {
nRF_WriteRegister(CONFIG, 0x0E); // TX Control
CE_Low(); // TX Mode
}
}
void nRF_Flush() {
CSN_Low(); // Enable chip
SPI_Write(FLUSH_TX);
CSN_High(); // Disable chip
CSN_Low(); // Enable chip
SPI_Write(FLUSH_RX);
CSN_High(); // Disable chip
}
void nRF_SendData(char* buffer) {
nRF_SetMode(TX_MODE);
nRF_WriteBuffer(W_TX_PAYLOAD, buffer, PAYLOAD_BYTES);
CE_High(); // RX Mode
__delay_ms(1);
CE_Low(); // TX Mode
}
void CE_High(){
PORTBbits.RB5 = 1;
}
void CE_Low() {
PORTBbits.RB5 = 0;
}
void CSN_High() {
PORTCbits.RC6 = 1;
}
void CSN_Low() {
PORTCbits.RC6 = 0;
}
void CSN_DDR_Low(){
TRISCbits.TRISC6 = 0;
}
void CE_DDR_Low() {
TRISBbits.TRISB5 = 0;
}
and nRF24L01.h
#ifndef NRF24L01
#define NRF24L01
#include <xc.h> // include processor files - each processor file is guarded.
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 8000000
#endif
// CE Pin RB5
// SS Pin RC6
// SDI Pin RB4
// SDO Pin RC7
// SCK Pin RB6
void nRF_Init(char, char);
void nRF_WriteRegister(char, char);
void SPI_Write(char);;
void nRF_WriteBuffer(char, char *, char);
void nRF_SetMode(char);
void nRF_Flush(void);
void nRF_SendData(char *);
void CE_High(void);
void CE_Low(void);
void CSN_High(void);
void CSN_Low(void);
void CSN_DDR_High(void);
void CSN_DDR_Low(void);
void CE_DDR_High(void);
void CE_DDR_Low(void);
#define PAYLOAD_BYTES 5 // Sets the bytes to send or read.
#define RX_MODE 1
#define TX_MODE 0
//==============================================================================
// Register Map.
//==============================================================================
#define R_REGISTER 0x00
#define W_REGISTER 0x20
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define CONFIG 0x00
#define EN_AA 0x01
#define EN_RXADDR 0x02
#define SETUP_AW 0x03
#define SETUP_RETR 0x04
#define RF_CH 0x05
#define RF_SETUP 0x06
#define STATUS_N 0x07
#define OBSERVE_TX 0x08
#define CD 0x09
#define RX_ADDR_P0 0x0A
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#endif
I am fairly new to MCU’s and SPI’s in general so anything would help. Thank you.