专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
物联网
求解NRF24L01无线模块
2019-07-18 14:42
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
RF/无线
6877
19
1072
我是大二的学生 参加飞思卡尔智能汽车比赛,用到了无线模块NRF24L01 ,但我学习了好久还是有很多不懂得地方,求大神指导,
无线模块与
单片机
如何连接(STC89C52 IO口),无线模块是如何发送数据的, 如果我用一个单片机+无线模块发数据给另一个单片+无线模块,希望点亮第二块单片机板子上的流水灯,那么发的是什么数据,????
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
19条回答
Eric-8
2019-07-20 01:07
89C52 、NRF24L01+、1602液晶显示 我昨晚刚调成。
无线确实难调,前前后后花了我近一个月呐!几次想放弃了都!但比赛作品需要它来润 {MOD},不得不咬牙坚持下来。功夫不负有心人啊!加油,你也可以的!
有一个特别头疼的问题就是当你去辛辛苦苦打完一整篇代码,完了一编译,艹!各种奇葩错误。比如明明定义了它却说没定义。所以最好每写一段编译一下。还有调试一定要一块块板子来。先把每块板子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); //多次重发失败时显示
}
}
}
加载中...
查看其它19个回答
一周热门
更多
>
相关问题
STM32开发板免费用活动
7 个回答
无线通讯电子电路图
3 个回答
求3DA92 3DA89 3DA37 高频放大管的外围电路
1 个回答
中波收音机为什么通常要采用环形天线呢?
4 个回答
相关文章
物联网通信协议——物联网数据协议
0个评论
基于AM335X的物联网关解决方案
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
物联网
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
无线确实难调,前前后后花了我近一个月呐!几次想放弃了都!但比赛作品需要它来润 {MOD},不得不咬牙坚持下来。功夫不负有心人啊!加油,你也可以的!
有一个特别头疼的问题就是当你去辛辛苦苦打完一整篇代码,完了一编译,艹!各种奇葩错误。比如明明定义了它却说没定义。所以最好每写一段编译一下。还有调试一定要一块块板子来。先把每块板子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); //多次重发失败时显示
}
}
}
一周热门 更多>