- 易迪拓培训,专注于微波、射频、天线设计工程师的培养
求解NRF24L01无线模块
无线模块与单片机如何连接(STC89C52 IO口),无线模块是如何发送数据的, 如果我用一个单片机+无线模块发数据给另一个单片+无线模块,希望点亮第二块单片机板子上的流水灯,那么发的是什么数据,?
你去看一下SPI总线的时序图,nRF24L01芯片和单片机连接最主要的就是这个时序问题.
嗯 ,那个时序图我看了好几天,有好多地方看不懂 !我再看看 ,如果再不会 那是向你请教,,希望不吝赐教
很好的学习。谢谢。
目前正在弄,头疼呢。
我也不懂,只是想做成个无线遥控而已
同问,有没有人能给一份程序,不胜感激
小编很复杂啊,糊涂了,mcu的。你是不是用的是射频前端啊?
看看例子就明白了
19940827邀请您访问中国电子技术论坛
http://bbs.elecfans.com/?fromuser=19940827
恩恩,希望谁给一个历程
你不妨看看这个:
89C52RC + NRF24L01 + 1602液晶显示 我昨晚刚调出来的。这家伙前前后后花了
我近一个月时间呐!对我这种小白,无线实在难搞,太狗血了!几次想放弃了,
但比赛作品需要它来润色,不得不咬牙坚持了下来。当看到接收机上亮起数字时,
我已老泪纵横了!
最容易出毛病的就是整篇代码打完后一编译,各种奇葩错误!明明定义过了还说undefined!
还有什么语法错误啦。最好写一段编译一下(代码度娘上太多了)。然后,调试的时候
一定要一块块来,先是MCU和NRF之间的通讯,然后检测载波,两块板子都OK了再进行无线
传输的调试!
发射程序:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
//****************************************IO端口定义***************************************
sbit IRQ=P2^2;
sbit MISO=P2^3;
sbit MOSI=P2^1;
sbit SCK=P2^4;
sbit CSN=P2^0;
sbit CE=P2^5;
sbit rs=P3^3;
sbit rw=P3^4;
sbit en=P3^5;
uchar bdata sta; //状态标志 // bData是可位寻址的变量
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
//uchar str[7];
//***************************************NRF24L01*************************************
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 4 // 3 uints TX payload //到底几位?
#define RX_PLOAD_WIDTH 4 // 3 uints TX payload
uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
uchar Tx_Buf[TX_PLOAD_WIDTH]={0x00,0x01,0x02,0x03};//发送数据
//uchar Rx_Buf[RX_PLOAD_WIDTH];//接收数据
//******************************NRF24L01寄存器指令***********************************
#define READ_REG 0x00 // 读寄存器指令
#define WRITE_REG 0x20 // 写寄存器指令
#define RD_RX_PLOAD 0x61 // 读取接收数据指令
#define WR_TX_PLOAD 0xA0 // 写待发数据指令
#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令
#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令
#define NOP 0xFF // 空指令 可用于读状态寄存器
//******************************SPI(nRF24L01)寄存器地址******************************
#define CONFIG 0x00 //配置收发状态,CRC校验模式以及收发状态响应方式
#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 0x07 // 状态寄存器
#define OBSERVE_TX 0x08 // 发送监测功能
#define CD 0x09 // 地址检测
#define RX_ADDR_P0 0x0A // 频道0接收数据地址
#define RX_ADDR_P1 0x0B // 频道1接收数据地址
#define RX_ADDR_P2 0x0C // 频道2接收数据地址
#define RX_ADDR_P3 0x0D // 频道3接收数据地址
#define RX_ADDR_P4 0x0E // 频道4接收数据地址
#define RX_ADDR_P5 0x0F // 频道5接收数据地址
#define TX_ADDR 0x10 // 发送地址寄存器
#define RX_PW_P0 0x11 // 接收频道0接收数据长度
#define RX_PW_P1 0x12 // 接收频道0接收数据长度
#define RX_PW_P2 0x13 // 接收频道0接收数据长度
#define RX_PW_P3 0x14 // 接收频道0接收数据长度
#define RX_PW_P4 0x15 // 接收频道0接收数据长度
#define RX_PW_P5 0x16 // 接收频道0接收数据长度
#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置
void delay(uchar z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//******************************** 液 晶 *************************************
void write_com(uchar com)
{
rs=0;
en=0;
P1=com;
delay(3);
en=1;
delay(3);
en=0;
}
void write_date(uchar date)
{
rs=1;
en=0;
P1=date;
delay(3);
en=1;
delay(3);
en=0;
}
void init_lcd() //光标关闪烁
{
en=0;
rw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06); //写一个字光标右移一位
write_com(0x01); //清屏
}
void display(uchar add,uchar temp) //显示函数
{
uchar shi,ge,yi;
shi=temp/100;
ge=temp%100/10;
yi=temp%10;
write_com(0x80+add);
if(shi==0)
{
write_date(' ');
}
else
{
write_date(0x30+shi);
}
write_date(0x30+ge);
write_date(0x30+yi);
}
//****************************IO 口模拟SPI总线 代码*********************************
uchar SPI_RW(uchar byte) // 写一个byte //
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
MOSI=(byte&0x80); // 写一个 。CSN不用置低吗?//
byte=(byte<<1);
SCK=1;
byte|=MISO; // 读一个 //
SCK=0;
}
return(byte); // 读回来的byte //
}
uchar SPI_RW_Reg(uchar reg,uchar value) // 向寄存器reg写一个字节(value),同时返回状态字节
{
uchar status;
CSN=0;
status=SPI_RW(reg);
SPI_RW(value);
CSN=1;
return(status);
}
uchar SPI_Read(uchar reg)
{
uchar reg_val;
CSN=0;
SPI_RW(reg);
reg_val=SPI_RW(0); // 读取寄存器reg 状态。发送0,读回byte 给reg_val //
CSN=1;
return(reg_val);
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) // 选择 reg 写入 *pBuf 的地址 ,bytes 地址长度 // //怎么起到选择作用?
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again
return(status); // return nRF24L01 status byte
}
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)//吧reg里数据读到buf里
{
uchar status,uchar_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar
for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)
pBuf[uchar_ctr] = SPI_RW(0); //
CSN = 1;
return(status); // return nRF24L01 status uchar
}
/******************************* 发 ***** 送 ***** 模 **** 式 ***** 代 ***** 码 *************************************/
void TX_Mode(void) //初始化!
{
CE=0;
SPI_RW_Reg(FLUSH_TX,0x00);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0 // 向EN_AA写入0x01,通道0自动应答.
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 向自动重发寄存器写入0x1a,等待500+86us,重发10次
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40 //向RF_CH写入40,频率为40....? //?
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f); // 向RF_SETUP 写入0x0f,传输率2Mbps 发射功率0dBm 低噪声放大增益器。
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节 //不是32字节? //?
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // 向CONFIG写入0x0e,CRC使能,CRC校验码16位,上电,发送模式。
CE=1; //CE高启动发射(10us之后)
delay(100);
}
void Transmit(uchar * tx_buf) // 发送数据
{
CE=0; //StandBy I模式
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_RW_Reg(FLUSH_TX,0x00);
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载tx_buf数据(写到PLOAD里)
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
CE=1; //置高CE,激发数据发送
delay(150);
}
void main()
{
// uchar status,FIFO;
CE=0;
SCK=0;
CSN=1;
IRQ=1;
status=0;
init_lcd();
delay(10);
TX_Mode();
// SPI_RW_Reg(FLUSH_TX,0x00);
// SPI_RW_Reg(WRITE_REG+STATUS,0xff);
while(1)
{
Tx_Buf[0]++;
Transmit(Tx_Buf);
delay(1000);
delay(1000);
delay(1000); //控制数字变化速度
//***********************************读寄存器状态******************************************
/* status=SPI_Read_Buf(TX_ADDR,str,TX_ADR_WIDTH);
display(0x00,str[0]);
display(0x04,str[1]);
display(0x08,str[2]);
display(0x0c,str[3]);
display(0x40,str[4]);
display(0x44,str[5]);
delay(10);*/ //读发射机地址
status=SPI_Read(STATUS);
display(0x00,status);
FIFO=SPI_Read(FIFO_STATUS);
display(0x04,FIFO);
Transmit(Tx_Buf);
status=SPI_Read(STATUS);
display(0x40,status);
FIFO=SPI_Read(FIFO_STATUS);
display(0x44,FIFO);
//************************************发送失败检测*********************************************
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据发送状况
if(!TX_DS)
{
write_com(0x88);
write_date('T');
write_date('X');
write_date(' ');
write_date('E');
write_date('R');
write_date('R');
write_date('O');
write_date('R'); //发送失败(没收到应答信号)
delay(5);
}
if(MAX_RT)
{
write_com(0X80+0x48);
write_date('R');
write_date('E');
write_date(' ');
write_date('E');
write_date('R');
write_date('R');
write_date('O');
write_date('R');
delay(5); //多次重发失败
}
}
}
还有接收部分:
89C52 、NRF24L01+、1602液晶显示 我昨晚刚调成。
无线确实难调,前前后后花了我近一个月呐!几次想放弃了都!但比赛作品需要它来润色,不得不咬牙坚持下来。功夫不负有心人啊!加油,你也可以的!
有一个特别头疼的问题就是当你去辛辛苦苦打完一整篇代码,完了一编译,艹!各种奇葩错误。比如明明定义了它却说没定义。所以最好每写一段编译一下。还有调试一定要一块块板子来。先把每块板子MCU和NRF之间的通讯建立完成,然后检测载波,再才是两板子之间一对一的无线收发调试。
这是发射部分:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
//****************************************IO端口定义***************************************
sbit IRQ=P2^2;
sbit MISO=P2^3;
sbit MOSI=P2^1;
sbit SCK=P2^4;
sbit CSN=P2^0;
sbit CE=P2^5;
sbit rs=P3^3;
sbit rw=P3^4;
sbit en=P3^5;
uchar bdata sta; //状态标志 // bData是可位寻址的变量
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
//uchar str[7];
//***************************************NRF24L01*************************************
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 4 // 3 uints TX payload //到底几位?
#define RX_PLOAD_WIDTH 4 // 3 uints TX payload
uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
uchar Tx_Buf[TX_PLOAD_WIDTH]={0x00,0x01,0x02,0x03};//发送数据
//uchar Rx_Buf[RX_PLOAD_WIDTH];//接收数据
//******************************NRF24L01寄存器指令***********************************
#define READ_REG 0x00 // 读寄存器指令
#define WRITE_REG 0x20 // 写寄存器指令
#define RD_RX_PLOAD 0x61 // 读取接收数据指令
#define WR_TX_PLOAD 0xA0 // 写待发数据指令
#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令
#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令
#define NOP 0xFF // 空指令 可用于读状态寄存器
//******************************SPI(nRF24L01)寄存器地址******************************
#define CONFIG 0x00 //配置收发状态,CRC校验模式以及收发状态响应方式
#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 0x07 // 状态寄存器
#define OBSERVE_TX 0x08 // 发送监测功能
#define CD 0x09 // 地址检测
#define RX_ADDR_P0 0x0A // 频道0接收数据地址
#define RX_ADDR_P1 0x0B // 频道1接收数据地址
#define RX_ADDR_P2 0x0C // 频道2接收数据地址
#define RX_ADDR_P3 0x0D // 频道3接收数据地址
#define RX_ADDR_P4 0x0E // 频道4接收数据地址
#define RX_ADDR_P5 0x0F // 频道5接收数据地址
#define TX_ADDR 0x10 // 发送地址寄存器
#define RX_PW_P0 0x11 // 接收频道0接收数据长度
#define RX_PW_P1 0x12 // 接收频道0接收数据长度
#define RX_PW_P2 0x13 // 接收频道0接收数据长度
#define RX_PW_P3 0x14 // 接收频道0接收数据长度
#define RX_PW_P4 0x15 // 接收频道0接收数据长度
#define RX_PW_P5 0x16 // 接收频道0接收数据长度
#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置
void delay(uchar z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//******************************** 液 晶 *************************************
void write_com(uchar com)
{
rs=0;
en=0;
P1=com;
delay(3);
en=1;
delay(3);
en=0;
}
void write_date(uchar date)
{
rs=1;
en=0;
P1=date;
delay(3);
en=1;
delay(3);
en=0;
}
void init_lcd() //光标关闪烁
{
en=0;
rw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06); //写一个字光标右移一位
write_com(0x01); //清屏
}
void display(uchar add,uchar temp) //显示函数
{
uchar shi,ge,yi;
shi=temp/100;
ge=temp%100/10;
yi=temp%10;
write_com(0x80+add);
if(shi==0)
{
write_date(' ');
}
else
{
write_date(0x30+shi);
}
write_date(0x30+ge);
write_date(0x30+yi);
}
//****************************IO 口模拟SPI总线 代码*********************************
uchar SPI_RW(uchar byte) // 写一个byte //
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
MOSI=(byte&0x80); // 写一个 。CSN不用置低吗?//
byte=(byte<<1);
SCK=1;
byte|=MISO; // 读一个 //
SCK=0;
}
return(byte); // 读回来的byte //
}
uchar SPI_RW_Reg(uchar reg,uchar value) // 向寄存器reg写一个字节(value),同时返回状态字节
{
uchar status;
CSN=0;
status=SPI_RW(reg);
SPI_RW(value);
CSN=1;
return(status);
}
uchar SPI_Read(uchar reg)
{
uchar reg_val;
CSN=0;
SPI_RW(reg);
reg_val=SPI_RW(0); // 读取寄存器reg 状态。发送0,读回byte 给reg_val //
CSN=1;
return(reg_val);
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) // 选择 reg 写入 *pBuf 的地址 ,bytes 地址长度 // //怎么起到选择作用?
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again
return(status); // return nRF24L01 status byte
}
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)//吧reg里数据读到buf里
{
uchar status,uchar_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar
for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)
pBuf[uchar_ctr] = SPI_RW(0); //
CSN = 1;
return(status); // return nRF24L01 status uchar
}
/******************************* 发 ***** 送 ***** 模 **** 式 ***** 代 ***** 码 *************************************/
void TX_Mode(void) //初始化!
{
CE=0;
SPI_RW_Reg(FLUSH_TX,0x00);
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0 // 向EN_AA写入0x01,通道0自动应答.
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 向自动重发寄存器写入0x1a,等待500+86us,重发10次
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40 //向RF_CH写入40,频率为40.....?
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f); // 向RF_SETUP 写入0x0f,传输率2Mbps 发射功率0dBm 低噪声放大增益器。
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为4字节
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // 向CONFIG写入0x0e,CRC使能,CRC校验码16位,上电,发送模式。
CE=1; //CE高启动发射(10us之后)
delay(100);
}
void Transmit(uchar * tx_buf) // 发送数据
{
CE=0; //StandBy I模式
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_RW_Reg(FLUSH_TX,0x00); //清空TX FIFO
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载tx_buf数据
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
CE=1; //置高CE,激发数据发送
delay(150);
}
void main()
{
// uchar status,FIFO; //后面读状态时候用
CE=0;
SCK=0;
CSN=1;
IRQ=1;
// status=0; //后面读状态时候用.先设为0
init_lcd();
delay(10);
TX_Mode();
// SPI_RW_Reg(FLUSH_TX,0x00);
// SPI_RW_Reg(WRITE_REG+STATUS,0xff);
while(1)
{
Transmit(Tx_Buf);
delay(10);
//***********************************读寄存器状态******************************************
/* status=SPI_Read_Buf(TX_ADDR,str,TX_ADR_WIDTH);
display(0x00,str[0]);
display(0x04,str[1]);
display(0x08,str[2]);
display(0x0c,str[3]);
display(0x40,str[4]);
display(0x44,str[5]);
delay(10);*/ //读发射机地址(单独调试时用)
status=SPI_Read(STATUS); //读STATUS状态
display(0x00,status);
FIFO=SPI_Read(FIFO_STATUS); //读FIFO状态
display(0x04,FIFO);
Transmit(Tx_Buf); // 发送一次
status=SPI_Read(STATUS); //再读
display(0x40,status);
FIFO=SPI_Read(FIFO_STATUS);
display(0x44,FIFO);
//************************************发送失败检测*********************************************
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据发送状况
if(!TX_DS)
{
write_com(0x88);
write_date('T');
write_date('X');
write_date(' ');
write_date('E');
write_date('R');
write_date('R');
write_date('O');
write_date('R'); //发送失败(没收到应答信号)时显示
delay(5);
}
if(MAX_RT)
{
write_com(0X80+0x48);
write_date('R');
write_date('E');
write_date(' ');
write_date('E');
write_date('R');
write_date('R');
write_date('O');
write_date('R');
delay(5); //多次重发失败时显示
}
}
}
发送代码我好想发了两次诶,,,
结下来是接收部分的代码:
#include <reg52.h> //接收部分
#define uchar unsigned char
#define uint unsigned int
//****************************************IO端口定义***************************************
sbit IRQ=P2^2;
sbit MISO=P2^3;
sbit MOSI=P2^1;
sbit SCK=P2^4;
sbit CSN=P2^0;
sbit CE=P2^5;
sbit rs=P3^3;
sbit rw=P3^4;
sbit en=P3^5;
uchar bdata sta; //状态标志 // bData是可位寻址的变量
sbit RX_DR =sta^6;
sbit TX_DS =sta^5;
sbit MAX_RT =sta^4;
uchar f; //标志位
//uchar str[7];
//***************************************NRF24L01*************************************
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 4 //4 uints TX payload
#define RX_PLOAD_WIDTH 4 // 4 uints TX payload
uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //发射机地址
uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
//uchar code Tx_Buf[TX_PLOAD_WIDTH]={0x00,0x01,0x02,0x03};//发送数据
uchar Rx_Buf[RX_PLOAD_WIDTH];//接收数据
//******************************NRF24L01寄存器指令***********************************
#define READ_REG 0x00 // 读寄存器指令
#define WRITE_REG 0x20 // 写寄存器指令
#define RD_RX_PLOAD 0x61 // 读取接收数据指令
#define WR_TX_PLOAD 0xA0 // 写待发数据指令
#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令
#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令
#define NOP 0xFF // 空指令 可用于读状态寄存器
//******************************SPI(nRF24L01)寄存器地址******************************
#define CONFIG 0x00 //配置收发状态,CRC校验模式以及收发状态响应方式
#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 0x07 // 状态寄存器
#define OBSERVE_TX 0x08 // 发送监测功能
#define CD 0x09 // 地址检测
#define RX_ADDR_P0 0x0A // 频道0接收数据地址
#define RX_ADDR_P1 0x0B // 频道1接收数据地址
#define RX_ADDR_P2 0x0C // 频道2接收数据地址
#define RX_ADDR_P3 0x0D // 频道3接收数据地址
#define RX_ADDR_P4 0x0E // 频道4接收数据地址
#define RX_ADDR_P5 0x0F // 频道5接收数据地址
#define TX_ADDR 0x10 // 发送地址寄存器
#define RX_PW_P0 0x11 // 接收频道0接收数据长度
#define RX_PW_P1 0x12 // 接收频道0接收数据长度
#define RX_PW_P2 0x13 // 接收频道0接收数据长度
#define RX_PW_P3 0x14 // 接收频道0接收数据长度
#define RX_PW_P4 0x15 // 接收频道0接收数据长度
#define RX_PW_P5 0x16 // 接收频道0接收数据长度
#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//******************************** 液 晶 *************************************
void write_com(uchar com)
{
rs=0;
en=0;
P1=com;
delay(3);
en=1;
delay(3);
en=0;
}
void write_date(uchar date)
{
rs=1;
en=0;
P1=date;
delay(3);
en=1;
delay(3);
en=0;
}
void init_lcd() //光标关闪烁
{
en=0;
rw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06); //写一个字光标右移一位
write_com(0x01); //清屏
}
void display(uchar add,uchar temp) //显示函数
{
uchar bai,shi,ge;
bai=temp/100;
shi=temp%100/10;
ge=temp%10;
write_com(0x80+add);
if(shi==0)
{
write_date(' ');
}
else
{
write_date(0x30+bai);
}
write_date(0x30+shi);
write_date(0x30+ge);
}
//****************************IO 口模拟SPI总线 代码*********************************
uchar SPI_RW(uchar byte) // 写一个byte //
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++)
{
MOSI=(byte&0x80); // 写一个 。CSN不用置低吗?//
byte=(byte<<1);
SCK=1;
byte|=MISO; // 读一个 //
SCK=0;
}
return(byte); // 读回来的byte //
}
uchar SPI_RW_Reg(uchar reg,uchar value) // 向寄存器reg写一个字节(value),同时返回状态字节
{
uchar status;
CSN=0;
status=SPI_RW(reg);
SPI_RW(value);
CSN=1;
return(status);
}
uchar SPI_Read(uchar reg)
{
uchar reg_val;
CSN=0;
SPI_RW(reg);
reg_val=SPI_RW(0); // 读取寄存器reg 状态。发送0,读回byte 给reg_val //
CSN=1;
return(reg_val);
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes) // 选择 reg 写入 *pBuf 的地址 ,bytes 地址长度 // //怎么起到选择作用?
{
uchar status,byte_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status byte
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again
return(status); // return nRF24L01 status byte
}
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)//吧reg里数据读到buf里
{
uchar status,uchar_ctr;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar
for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)
pBuf[uchar_ctr] = SPI_RW(0); //
CSN = 1;
return(status); // return nRF24L01 status uchar
}
/******************************************************************************************************/
/*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
/*功能:数据读取后放入rx_buf接收缓冲区中
/******************************************************************************************************/
void nRF24L01_RxPacket(uchar *rx_buf)
{
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
if(RX_DR) // 判断是否接收到数据
{
CE = 0; //SPI使能
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
f=1; //读取数据完成标志
}
SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清除中断标志
}
/****************************************************************************************************/
/*函数:void RX_Mode(void)
/*功能:数据接收配置
/****************************************************************************************************/
void RX_Mode(void) //接收模式
{
CE=0;
SPI_RW_Reg(FLUSH_RX,0x00);
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_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0 向EN_AA写入0x01,通道0自动应答.
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0
// SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1a 。接收模式不用写。
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为2字节
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
CE=1;
delay(130);
}
void Receive() //接收数据
{
CE=0;
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0F); //向CONFIG写入0x0f,CRC使能,CRC校验码16位,上电,接收模式。
CE=1;
delay(10);
}
void main()
{
uint i;
init_lcd();
CE=0;
SCK=0;
CSN=1;
IRQ=1;
RX_Mode();
while(1)
{
Receive(); //接收
nRF24L01_RxPacket(Rx_Buf); //数据存放到Rx_Buf[]
delay(10);
if(f) //接收到数据时f=1
{
display(0x00,Rx_Buf[0]);
display(0x08,Rx_Buf[1]);
display(0x40,Rx_Buf[2]);
display(0x48,Rx_Buf[3]);
delay(10);
}
else
{
write_com(0x80);
write_date(0x3a);
delay(10); //没收到时显示一个冒号
}
}
}
最后,祝你好运! 不要灰心,不要放弃,你会成功的!
先收藏了这个找了很多这种有点不靠谱
非常感谢!我会好好努力的!
谢谢大神 !我试试看看 !非常感谢
你做的是无线遥控汽车吗!
我也不懂,只是想做成个无线遥控而已
我是大二的学生 参加飞思卡尔智能汽车比赛,用到了无线模块NRF24L01 ,但我学习了好久还是有很多不懂得地方,求大神指导,
无线模块与单片机如何连接(STC89C52 IO口),无线模块是如何发送数据的, 如果我用一个单片机+无线模块发数据给另一个单片+无线模块,希望点亮第二块单片机板子上的流水灯,那么发的是什么数据,?
我司最新推出JTT1212超低功耗无线数传模块是成都江腾科技基于PIC单片机和Semtech SX1212开发的一款工作在430M至510M频段的远距离、高集成度无线数传模块;待机电流小于280nA,接收电流仅仅3mA,1S周期唤醒时电流低至15uA,在2.2V时仍能正常工作,一节2300mAh的锂亚电池可工作10年以上;具备大小组网模式,适合不同网络规模应用;良好的并发性,支持多对一同时传输;特别适合水、电、气、热表的集抄及对功耗有特别要求的应用。JTT1212模块采用屏蔽设计具有非常出色的抗干扰和穿透能力,已成功应用于安防、交通、能源、市政、工业遥控、工厂自动化、智能家居、现代农牧业等领域。
主要参数
工作电压 2.2-3.6V
发射电流 <30mA
接收电流 <3mA
待机电流 <280nA
输出功率 0-12dBm可调
工作频率 430MHz-440MHz或470MHz-510MHz
接口方式 2.0mm间距直插,方便嵌入式运用
接口 串口(UART)
接口电平 2~5V兼容
工作温度 -20℃—80℃
数据速率 1.2kbps-64kbps
接收灵敏度 -118dbm
外形尺寸 18mm×30mm(不含天线座)
搭配我司(2.5dbi增益)的胶棒天线,实测(空旷)500米稳定无压力,轻松 做到1000米有信号
需要详细资料请发邮件到2637633708@qq.com索取。
我这里有示例代码哟,。加我QQ:2637633708
先标记