求解NRF24L01无线模块

2019-07-18 14:42发布

我是大二的学生  参加飞思卡尔智能汽车比赛,用到了无线模块NRF24L01    ,但我学习了好久还是有很多不懂得地方,求大神指导,

无线模块与单片机如何连接(STC89C52  IO口),无线模块是如何发送数据的,  如果我用一个单片机+无线模块发数据给另一个单片+无线模块,希望点亮第二块单片机板子上的流水灯,那么发的是什么数据,????
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
Eric-8
1楼-- · 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);                           //多次重发失败时显示
               
                }

        }
}
Eric-8
2楼-- · 2019-07-20 05:38
 精彩回答 2  元偷偷看……
我是楼主呀
3楼-- · 2019-07-20 11:04
先收藏了这个找了很多这种有点不靠谱
李赵龙
4楼-- · 2019-07-20 12:59
Eric-8 发表于 2013-10-7 00:48
发送代码我好想发了两次诶,,,

结下来是接收部分的代码:

非常感谢!我会好好努力的!!!!

李赵龙
5楼-- · 2019-07-20 16:19
Eric-8 发表于 2013-10-7 00:37
89C52 、NRF24L01+、1602液晶显示   我昨晚刚调成。
无线确实难调,前前后后花了我近一个月呐!几次想放弃 ...

谢谢大神   !我试试看看  !非常感谢
李赵龙
6楼-- · 2019-07-20 19:04
 精彩回答 2  元偷偷看……

一周热门 更多>