📄 nrf24l01.c
字号:
#include <intrins.h>
#include "define.h"
#include "nrf24l01.h"
/***************************************************************************************/
/* NRF24L01 的管脚定义,以及在本程序中的应用,VCC接3.3V电源,可以通过5V用电压转换芯片
/*得到,NC 管脚可以接可以不接,暂时没用途。本程序应用于51或者52单片机,是两个模块进行通讯
/*成功的简单指示,现象是:模块1的 KEY1 对应模块1的LED1 和模块2的LED3 ,模块1的 KEY2 对应模
/*块1的LED2 和模块2的LED4,发过来也对应。
/***************************************************************************************/
/*****************************************长延时*****************************************/
void Delay(unsigned int s)
{
unsigned int i;
for(i=0; i<s; i++);
for(i=0; i<s; i++);
}
/******************************************************************************************/
/*延时函数
/******************************************************************************************/
void inerDelay_us(unsigned char n) //延时,us 级
{
for(;n>0;n--)
_nop_();
}
/****************************************************************************************/
/*NRF24L01初始化
/***************************************************************************************/
void init_NRF24L01(void)
{
inerDelay_us(100);
CE=0; // 芯片使能
CSN=1; // 禁止 SPI
SCK=0; // SPI时钟置低
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答允许
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21
SPI_RW_Reg(WRITE_REG + RF_CH, 0x02); // 设置信道工作为2.4GHZ,收发必须一致
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB
}
/****************************************************************************************************/
/*函数:unsigned int SPI_RW(unsigned int unsigned char)
/*功能:NRF24L01的SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节
/****************************************************************************************************/
unsigned int SPI_RW(unsigned int dat)
{
unsigned int i;
for(i=0;i<8;i++) // 循环8次
{
MOSI = (dat & 0x80); // dat的最高位输出到MOSI MSB to MOSI
inerDelay_us(DELAY);
dat = (dat << 1); // 从右向左进一位 shift next bit into MSB..
SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 Set SCK high..
inerDelay_us(DELAY);
dat |= MISO; //读MISO到 dat 最低位 capture current MISO bit
inerDelay_us(DELAY);
SCK = 0; // SCK置低 ..then set SCK low again
inerDelay_us(DELAY);
}
return(dat); //返回读出的一字节 return read dat
}
/****************************************************************************************************
/*函数:unsigned char SPI_Read(unsigned char reg)
/*功能:NRF24L01的SPI时序-----------从reg寄存器读一字节
/****************************************************************************************************/
unsigned char SPI_Read(unsigned char reg)
{
unsigned char reg_val;
CSN = 0; //CSN置低,开始传输数据 CSN low, initialize SPI communication...
inerDelay_us(DELAY);
SPI_RW(reg); //选择寄存器 Select register to read from..
reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalue
CSN = 1; //CSN拉高,结束数据传输 CSN high, terminate SPI communication
inerDelay_us(DELAY);
return(reg_val); //返回寄存器数据 return register value
}
/****************************************************************************************************/
/*功能:NRF24L01读写寄存器函数
/*描述:写数据value到reg寄存器
/****************************************************************************************************/
unsigned int SPI_RW_Reg(unsigned char reg, unsigned char value)
{
unsigned char status;
CSN = 0; // CSN置低,开始传输数据 CSN low, init SPI transaction
inerDelay_us(DELAY);
status = SPI_RW(reg); // 选择寄存器,同时返回状态字 select register
SPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..
CSN = 1; // CSN拉高,结束数据传输 CSN high again
inerDelay_us(DELAY);
return(status); // 返回状态寄存器 return nRF24L01 status unsigned char
}
/****************************************************************************************************/
/*函数:unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char unsigned chars)
/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,unsigned chars:读出数据的个数
/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址
/****************************************************************************************************/
unsigned int SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars)
{
unsigned int status,i;
CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranaction
inerDelay_us(DELAY);
status = SPI_RW(reg); //选择寄存器,同时返回状态字 Select register to write to and read status unsigned char
for(i=0;i<uchars;i++)
pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出
CSN = 1; //CSN拉高,结束数据传输
inerDelay_us(DELAY);
return(status); //返回状态寄存器 return nRF24L01 status unsigned char
}
/*********************************************************************************************************
/*函数:unsigned int SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char unsigned chars)
/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,unsigned chars:写入数据的个数
/*描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址
/*********************************************************************************************************/
unsigned int SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char uchars)
{
unsigned int status,i;
CSN = 0; //CSN置低,开始传输数据
inerDelay_us(DELAY);
status = SPI_RW(reg); //选择寄存器,同时返回状态字
inerDelay_us(DELAY);
for(i=0; i<uchars; i++)
SPI_RW(*pBuf++); //逐个字节写入nRF24L01
CSN = 1; //CSN拉高,结束数据传输
inerDelay_us(DELAY);
return(status); //返回状态寄存器
}
/****************************************************************************************************/
/*函数:void SetRX_Mode(void)
/*功能:数据接收配置
/****************************************************************************************************/
void SetRX_Mode(void)
{
CE=0;
inerDelay_us(DELAY);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC校验,上电,接收模式
CE = 1; // 拉高CE启动接收设备
inerDelay_us(DELAY);
inerDelay_us(130);
}
/******************************************************************************************************/
/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
/*功能:数据读取后放入rx_buf接收缓冲区中
/******************************************************************************************************/
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
unsigned char revale=0;
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
if(RX_DR) // 判断是否接收到数据
{
CE = 0; //SPI使能
inerDelay_us(DELAY);
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
revale =1; //读取数据完成标志
}
SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
return revale;
}
/***********************************************************************************************************
/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)
/*功能:发送 tx_buf中数据
/**********************************************************************************************************/
void nRF24L01_TxPacket(unsigned char * tx_buf)
{
CE=0; //StandBy I模式
inerDelay_us(DELAY);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
CE=1; //置高CE,激发数据发送
inerDelay_us(130);
}
void nRF24L01_Initial(void)
{
CE=0;// chip enable
CSN=1;// Spi disable
SCK=0;// Spi clock line init high
MOSI = 1;//mosi input
IRQ = 1;//IRQ input
}
/**************************************************
Function: RX_Mode();
Description:
This function initializes one nRF24L01 device to
RX Mode, set RX address, writes RX payload width,
select RF channel, datarate & LNA HCURR.
After init, CE is toggled high, which means that
this device is now ready to receive a datapacket. */
/**************************************************/
/*
void RX_Mode(void)
{
CE=0;
inerDelay_us(10);
// DI();
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // Use the same address on the RX device as the TX device
//SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); // disable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_AW, 0x03);//5byte的地址
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00);//禁止重发
SPI_RW_Reg(WRITE_REG + RF_CH, 20); // Select RF channel 2440M
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // Set PWR_UP bit, enable CRC(2 bytes) & Prim:RX. RX_DR enabled..
// EI();
CE=1;
inerDelay_us(500);
//IE0 = 0;
// This device is now ready to receive one packet of 16 bytes payload from a TX device sending to address
// '3443101001', with auto acknowledgment, retransmit count of 10, RF channel 40 and datarate = 2Mbps.
}*/
void RX_Mode(void)
{
CE=0;
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); //& Prim:RX. RX_DR enabled..
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);
CE = 1;
}
/**************************************************/
/**************************************************
Function: TX_Mode();
Description:
This function initializes one nRF24L01 device to
TX mode, set TX address, set RX address for auto.ack,
fill TX payload, select RF channel, datarate & TX pwr.
PWR_UP is set, CRC(2 bytes) is enabled, & PRIM:TX.
ToDo: One high pulse(>10us) on CE will now send this
packet and expext an acknowledgment from the RX device. */
/**************************************************/
/*
void TX_Mode(unsigned char *Rf_Send_Buf)
{
CE=0;
inerDelay_us(10);
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack
//SPI_Write_Buf(WR_TX_PLOAD, Buffer, TX_PLOAD_WIDTH); // Writes data to TX payload
SPI_Write_Buf(WR_TX_PLOAD, Rf_Send_Buf, TX_PLOAD_WIDTH); // Writes data to TX payload
//SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_AA, 0x00); // disable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_AW, 0x03);//5byte的地址
//SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00);//禁止重发
SPI_RW_Reg(WRITE_REG + RF_CH, 20); // Select RF channel 2440M
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); //设置发送数据长度,本次设置为32字节
//SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
SPI_RW_Reg(WRITE_REG + CONFIG, 0x3e);//
CE=1;
inerDelay_us(500);
SPI_RW_Reg(FLUSH_TX, 0x00);
SPI_RW_Reg(WRITE_REG + STATUS, 0x70);//RESET INTTERUPT
//IE0 = 0;
}
*/
void TX_Mode(unsigned char *Rf_Send_Buf)
{
CE=0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WR_TX_PLOAD, Rf_Send_Buf, TX_PLOAD_WIDTH); // Writes data to TX payload
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);
CE=1;
inerDelay_us(130);
}
void rec_rf_data(unsigned char *Rf_Rec_Buf)
{
SPI_Read_Buf(RD_RX_PLOAD,Rf_Rec_Buf,TX_PLOAD_WIDTH);
RX_Mode();
SPI_RW_Reg(WRITE_REG + STATUS, 0x70);//RESET INTTERUPT
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -