SolidDomo
Newbie
I've been struggling to get a PIC16F1829 and my nRF24L01+ to transmit data to an Arduino Uno with an nRF24L01+. I am new to MCU's and the SPI so anything would help.
Here's the code for the main.c:
nRF24L01.c:
and nRF24L01.h
Anything would help as I've been working on this for weeks. Thank you.
Here's the code for the main.c:
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);
}
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;
}
Code:
#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
Anything would help as I've been working on this for weeks. Thank you.