微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > 求解NRF24L01无线模块

求解NRF24L01无线模块

时间:10-02 整理:3721RD 点击:
我是大二的学生  参加飞思卡尔智能汽车比赛,用到了无线模块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);                                  //没收到时显示一个冒号
                }       
       
        }
}
最后,祝你好运! 不要灰心,不要放弃,你会成功的!  

先收藏了这个找了很多这种有点不靠谱

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

谢谢大神   !我试试看看  !非常感谢

你做的是无线遥控汽车吗!

我也不懂,只是想做成个无线遥控而已

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top