/*
* nrf24l01.c
*
* Created on: 2016年4月13日
* Author: CrazyCpu
*/
#include "stc15.h"
#include <string.h>
#include "nrf24l01.h"
#include "spi.h"
sbit NRF_CE = P1^4;
sbit NRF_CSN = P1^5;
sbit NRF_IRQ = P1^1;
#define Nrf_CSN_High NRF_CSN=1
#define Nrf_CSN_Low NRF_CSN=0
#define Nrf_CE_High NRF_CE=1
#define Nrf_CE_Low NRF_CE=0
#define Nrf_IRQ NRF_IRQ
/* 接收Px地址 */
const unsigned char Rx_Addr_P0[5] = {0xE7,0xE7,0xE7,0xE7,0xE7};
const unsigned char Rx_Addr_P1[5] = {0xC2,0xC2,0xC2,0xC2,0xC2};
const unsigned char Rx_Addr_P2[5] = {0xC2,0xC2,0xC2,0xC2,0xC3};
const unsigned char Rx_Addr_P3[5] = {0xC2,0xC2,0xC2,0xC2,0xC4};
const unsigned char Rx_Addr_P4[5] = {0xC2,0xC2,0xC2,0xC2,0xC5};
const unsigned char Rx_Addr_P5[5] = {0xC2,0xC2,0xC2,0xC2,0xC6};
/* 发送地址 */
const unsigned char Tx_Addr[5] = {0xE7,0xE7,0xE7,0xE7,0xE7};
/* nrf24l01状态 */
volatile unsigned char Nrf_Status = 0x00;
extern void Delay10ms(); //@11.0592MHz
void Nrf24l01_Init(void)
{
/* SPI通信初始化 */
SPI_Init();
Nrf_CSN_High;
Nrf_CE_Low;
/* Nrf24l01 工作特点配置 */
Nrf24l01_Write_Register(CONFIG,0x0F); // 接收模式;接收、发送、最大重发次数中断使能;有CRC
Nrf24l01_Write_Register(SETUP_AW,0x03); // 5个字节地址宽度
Nrf24l01_Write_Register(SETUP_RETR,0x1A); // 等待 500+86us,自动重发10次
Nrf24l01_Write_Register(RF_CH,9); // 使用射频通道9
Nrf24l01_Write_Register(RF_SETUP,0x0F); // 2Mbps,0dbm
/*
The Data Ready interrupt is set by a new packet arrival event. The procedure for handling this interrupt should be:
1) read payload via SPI,
2) clear RX_DR interrupt,
3) read FIFO_STATUS to check if there are more payloads available in RX FIFO,
4) if there are more data in RX FIFO, repeat from 1).
*/
}
int Nrf24L01_Check(void)
{
unsigned char tmp_addr[5] = {0x53,0x53,0x53,0x53,0x53};
Nrf_CE_Low;
Nrf24l01_Write_Buff(TX_ADDR,(const unsigned char *)tmp_addr,Addr_Width);
memset(tmp_addr,0x00,5);
Nrf24l01_Read_Buff(TX_ADDR,tmp_addr,Addr_Width);
if((tmp_addr[0]==0x53) && (tmp_addr[1]==0x53) && (tmp_addr[2]==0x53) && (tmp_addr[3]==0x53) && (tmp_addr[4]==0x53))
return 0;
else
return 1;
}
void Nrf24l01_Write_Register(unsigned char cmd_addr,unsigned char byte)
{
Nrf_CSN_Low;
SPI_RW_Byte(cmd_addr|W_REG_CMD);
SPI_RW_Byte(byte);
Nrf_CSN_High;
}
unsigned char Nrf24l01_Read_Register(unsigned char cmd_addr)
{
unsigned char res = 0x00;
Nrf_CSN_Low;
SPI_RW_Byte(cmd_addr|R_REG_CMD);
res = SPI_RW_Byte(0xFF);
Nrf_CSN_High;
return res;
}
void Nrf24l01_Write_Buff(unsigned char cmd_addr,const unsigned char *buff,int width)
{
int k = 0;
Nrf_CSN_Low;
SPI_RW_Byte(cmd_addr|W_REG_CMD);
for(k=0; k<width; k++)
{
SPI_RW_Byte(*buff);
buff++;
}
Nrf_CSN_High;
}
void Nrf24l01_Read_Buff(unsigned char cmd_addr,unsigned char *buff,int width)
{
int k = 0;
Nrf_CSN_Low;
SPI_RW_Byte(cmd_addr|R_REG_CMD);
for(k=0; k<width; k++)
{
*buff = SPI_RW_Byte(0xFF);
buff++;
}
Nrf_CSN_High;
}
int Nrf24l01_TX_Packet( unsigned char *tx_buff, unsigned char width)
{
int res = 1;
Nrf_CE_Low;
/* 1 配置寄存器位 PRIM_RX 为低 */
Nrf24l01_Write_Register(CONFIG,NRF_TX_MODE);
/* 2 当 MCU 有数据要发送时 接收节点地址 TX_ADDR 和有效数据(TX_PLD)通过 SPI 接口写入nRF24L01 发送数据的长度以字节计数从 MCU 写入 TX FIFO */
Nrf24l01_Write_Buff(TX_ADDR,Tx_Addr,Addr_Width); // 发送地址
Nrf24l01_Write_Buff(W_TX_PAYLOAD,tx_buff,Data_Width); // 写入数据
/* 讲一个通道设置为接收来接收自动应答 */
Nrf24l01_Write_Register(EN_RXADDR,0x01); // P0 使能接收
Nrf24l01_Write_Buff(RX_ADDR_P0,Rx_Addr_P0,Addr_Width); // P0 接收地址
/* 3 设置 CE 为高 启动发射 CE 高电平持续时间最小为 10 us */
Nrf_CE_High;
while( Nrf_IRQ );
/* CE 置低 则系统进入待机模式 I */
Nrf_CE_Low;
Nrf_Status = Nrf24l01_Read_Register(STATUS);
/* 4.如果接收到有效应答,发送成功,TX_DS置1,IRQ中断,TX FIFO清除 */
if(Nrf_Status&TX_DS)
{
res = 0;
Nrf24l01_Write_Register(STATUS,TX_DS);
Nrf24l01_Write_Register(FLUSH_TX,0xFF);
}
/* 5.如果没有接收到有效应答,自动重发数据。如果自动重发计数器 ARC_CNT 溢出 ,MAX_RT置1, 不清除 TX FIFO,IRQ中断 */
if(Nrf_Status&MAX_RT)
{
res = 1;
Nrf24l01_Write_Register(STATUS,MAX_RT);
Nrf24l01_Write_Register(FLUSH_TX,0xFF);
}
if(Nrf_Status&RX_DR)
{
Nrf24l01_Write_Register(STATUS,RX_DR); // 以防万一,清除MAX_RT
Nrf24l01_Write_Register(FLUSH_RX,0xFF);
}
return res;
}
int Nrf24l01_RX_Packet(unsigned char *rx_buff,unsigned char width)
{
int res = 1;
Nrf_CE_Low;
/* 1.配置寄存器位 PRIM_RX 为高 */
Nrf24l01_Write_Register(CONFIG,NRF_RX_MODE);
/* 2.准备接收数据的通道必须被使能( EN_RXADDR 寄存器) */
Nrf24l01_Write_Register(EN_RXADDR,0x01); // P0 使能接收
Nrf24l01_Write_Register(EN_AA,0x01); // P0 自动应答
/* 3.有效数据宽度是由 RX_PW_Px 寄存器来设置 */
Nrf24l01_Write_Register(RX_PW_P0,Data_Width);
/* 4.地址建立 */
Nrf24l01_Write_Buff(RX_ADDR_P0,Rx_Addr_P0,Addr_Width);
/* 接收模式由设置 CE为高来启动 */
Nrf_CE_High;
/* 接收到有效的数据包后, 数据存储在 RX_FIFO 中,RX_DR 位置高 并产生中断,状态寄存器中 RX_P_NO 位显示数据是由哪个通道接收到的 */
while(Nrf_IRQ);
//delay_ms(10); // *****************************************
/* MCU 设置 CE 脚为低 进入待机模式 I */
Nrf_CE_Low;
/* MCU 将数据以合适的速率通过 SPI 口将数据读出 */
Nrf_Status = Nrf24l01_Read_Register(STATUS);
if(Nrf_Status&RX_DR)
{
res = 0;
Nrf24l01_Read_Buff(R_RX_PAYLOAD,rx_buff,width);
Nrf24l01_Write_Register(STATUS,RX_DR); // 清除RX_DR中断
Nrf24l01_Write_Register(FLUSH_RX,0xFF);
}
if(Nrf_Status&MAX_RT)
{
Nrf24l01_Write_Register(STATUS,MAX_RT);
Nrf24l01_Write_Register(FLUSH_TX,0xFF);
}
if(Nrf_Status&TX_DS)
{
Nrf24l01_Write_Register(STATUS,TX_DS);
Nrf24l01_Write_Register(FLUSH_TX,0xFF);
}
return res;
/* 芯片准备好进入发送模式 接收模式或掉电模式 */
}
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}