微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求助:nrf24l01无法实现通信,急求答案~~~~

求助:nrf24l01无法实现通信,急求答案~~~~

时间:10-02 整理:3721RD 点击:
网购了两个nRF24l01模块,想做无线收发功能,控制器分别为89C52和STC12c5A60s2,无线模块接口接在P0口,IRQ接到单片机P3^2,求助,接收端收不到信息,附程序,求大神解释一下~~~~~好几天还没解决;
接收端程序:
#include<reg52.h>
#include<api.h>
#define uint unsigned int
#define uchar unsigned char
#define LED P1
sbit key=P3^7;
/***************************************************/
#define TX_ADR_WIDTH   5  // 5字节宽度的发送/接收地址
#define TX_PLOAD_WIDTH 4  // 数据通道有效数据宽度
uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址
uchar RX_BUF[TX_PLOAD_WIDTH];
uchar TX_BUF[TX_PLOAD_WIDTH];
uchar flag;
uchar DATA = 0x01;
uchar bdata sta;
sbit  RX_DR     = sta^6;
sbit  TX_DS     = sta^5;
sbit  MAX_RT = sta^4;
/**************************************************
函数: init_io()
描述:
    初始化IO
/**************************************************/
void init_io(void)
{
    CE  = 0;        // 待机
    CSN = 1;        // SPI禁止
    SCK = 0;        // SPI时钟置低
    IRQ = 1;        // 中断复位
//    LED = 0xff;        // 关闭指示灯
}
/**************************************************
函数:delay()
描述:延时函数
**************************************************/
void delay(uint z)
{
    uint x;
    while(z--)
        for(x=110;x>0;x--);
}
/**************************************************
函数:SPI_RW()
描述:
    根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
    读出一字节
/**************************************************/
uchar SPI_RW(uchar byte)
{
    uchar i;
    for(i=0;i<8;i++)
    {
        MOSI=(byte&0x80);
        byte<<=1;
        SCK=1;
        byte|=MISO;
        SCK=0;
    }
    return (byte);
}
/**************************************************
函数:SPI_RW_Reg()
描述:
    写数据value到reg寄存器
/**************************************************/
uchar SPI_RW_REG(uchar reg,uchar value)
{
    uchar status;
    CSN=0;
    status=SPI_RW(reg);
    SPI_RW(value);
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Read()
描述:
    从reg寄存器读一字节
/**************************************************/
uchar SPI_READ(uchar reg)
{
    uchar status,reg_val;
    CSN=0;
    SPI_RW(reg);
    reg_val=SPI_RW(0);
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Read_Buf()
描述:
    从reg寄存器读出bytes个字节,通常用来读取接收通道
    数据或接收/发送地址
/**************************************************/
uchar SPI_READ_BUF(uchar reg,uchar *pBUF,uchar byte)
{
    uchar status,i;
    CSN=0;
    status=SPI_RW(reg);
    for(i=0;i<byte;i++)
    {
        pBUF=SPI_RW(0);
    }
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Write_Buf()
描述:
    把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
    射通道数据或接收/发送地址
/**************************************************/
uchar SPI_WRITE_BUF(uchar reg,uchar *pBUF,uchar byte)
{
    uchar status,i;
    CSN=0;
    status=SPI_RW(reg);
    for(i=0;i<byte;i++)
        SPI_RW(*pBUF++);
    CSN=1;
    return(status);   
}
/**************************************************
函数:RX_Mode()
描述:
    这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
void RX_MODE()
{
    CE=0;
    SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
    SPI_RW_REG(WRITE_REG+EN_AA,0X01);
    SPI_RW_REG(WRITE_REG+EN_RXADDR,0X01);
    SPI_RW_REG(WRITE_REG+RF_CH,40);
    SPI_RW_REG(WRITE_REG+RX_PW_P0,TX_PLOAD_WIDTH);
    SPI_RW_REG(WRITE_REG+RF_SETUP,0X07);
    SPI_RW_REG(WRITE_REG+CONFIG,0x0f);
    CE=1;
}
/**************************************************
函数:TX_Mode()
描述:
    这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),
    130us后启动发射,数据发送结束后,发送模块自动转入接收
    模式等待应答信号。
/**************************************************/
void TX_MODE(uchar *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,BUF,TX_PLOAD_WIDTH);
    SPI_RW_REG(WRITE_REG+EN_AA,0X01);
    SPI_RW_REG(WRITE_REG+EN_RXADDR,0X01);
    SPI_RW_REG(WRITE_REG+SETUP_RETR,0X1A);
    SPI_RW_REG(WRITE_REG+RF_CH,40);
    SPI_RW_REG(WRITE_REG+RF_SETUP,0X07);
    SPI_RW_REG(WRITE_REG+CONFIG,0x0E);
    CE=1;
}
/**************************************************
函数:Check_ACK()
描述:
    检查接收设备有无接收到数据包,设定没有收到应答信
    号是否重发
/**************************************************/
uchar Check_ACK(bit clear)
{
    while(IRQ);
    sta = SPI_RW(NOP);                    // 返回状态寄存器
    if(MAX_RT)
        if(clear)                         // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发
            SPI_RW(FLUSH_TX);
    SPI_RW_REG(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
    IRQ = 1;
    if(TX_DS)
        return(0x00);
    else
        return(0xff);
}
/**************************************************
函数:keyscan()
描述:检测是否有按键按下,按下则发送一字节数据
**************************************************
void keyscan()
{
    if(key==0)
    {
        delay(5);
        if(key==0)
        {
            TX_BUF[0]=~DATA;
            TX_MODE(TX_BUF);
            LED=~DATA;
            Check_ACK(1);
            delay(500);
            LED=0XFF;
            while(!key);
            DATA<<=1;
            if(!DATA)
                DATA=0x01;   
        }
    }
}
************************************************/
void main()
{
    init_io();
    RX_MODE();
    while(1)
    {
        sta=SPI_READ(STATUS);
        if(RX_DR)
        {
            SPI_READ_BUF(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);
            flag=1;
        }
        SPI_RW_REG(WRITE_REG+STATUS,sta);
        if(flag)
        {
            flag=0;
            LED=RX_BUF[0];
        }            
    }
}
发送端程序
#include<reg52.h>
#include<api.h>
#define uint unsigned int
#define uchar unsigned char
#define LED P1
sbit key=P3^7;
//sbit beep=P2^5;
//sbit wela=P2^6;
//sbit dula=P2^7;
/***************************************************/
#define TX_ADR_WIDTH   5  // 5字节宽度的发送/接收地址
#define TX_PLOAD_WIDTH 4  // 数据通道有效数据宽度
uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址
uchar RX_BUF[TX_PLOAD_WIDTH];
uchar TX_BUF[TX_PLOAD_WIDTH];
uchar flag;
uchar DATA = 0x01;
uchar bdata sta;
sbit  RX_DR     = sta^6;
sbit  TX_DS     = sta^5;
sbit  MAX_RT = sta^4;
/**************************************************
函数: init_io()
描述:
    初始化IO
/**************************************************/
void init_io(void)
{
   // dula=0;
   // wela=0;
    CE  = 0;        // 待机
    CSN = 1;        // SPI禁止
    SCK = 0;        // SPI时钟置低
    IRQ = 1;        // 中断复位
//    LED = 0xff;        // 关闭指示灯
}
/**************************************************
函数:delay()
描述:延时函数
**************************************************/
void delay(uint z)
{
    uint x;
    while(z--)
        for(x=110;x>0;x--);
}
/**************************************************
函数:SPI_RW()
描述:
    根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
    读出一字节
/**************************************************/
uchar SPI_RW(uchar byte)
{
    uchar i;
    for(i=0;i<8;i++)
    {
        MOSI=(byte&0x80);
        byte<<=1;
        SCK=1;
        byte|=MISO;
        SCK=0;
    }
    return (byte);
}
/**************************************************
函数:SPI_RW_Reg()
描述:
    写数据value到reg寄存器
/**************************************************/
uchar SPI_RW_REG(uchar reg,uchar value)
{
    uchar status;
    CSN=0;
    status=SPI_RW(reg);
    SPI_RW(value);
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Read()
描述:
    从reg寄存器读一字节
/**************************************************/
uchar SPI_READ(uchar reg)
{
    uchar status,reg_val;
    CSN=0;
    SPI_RW(reg);
    reg_val=SPI_RW(0);
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Read_Buf()
描述:
    从reg寄存器读出bytes个字节,通常用来读取接收通道
    数据或接收/发送地址
/**************************************************/
uchar SPI_READ_BUF(uchar reg,uchar *pBUF,uchar byte)
{
    uchar status,i;
    CSN=0;
    status=SPI_RW(reg);
    for(i=0;i<byte;i++)
    {
        pBUF=SPI_RW(0);
    }
    CSN=1;
    return(status);
}
/**************************************************
函数:SPI_Write_Buf()
描述:
    把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
    射通道数据或接收/发送地址
/**************************************************/
uchar SPI_WRITE_BUF(uchar reg,uchar *pBUF,uchar byte)
{
    uchar status,i;
    CSN=0;
    status=SPI_RW(reg);
    for(i=0;i<byte;i++)
        SPI_RW(pBUF);
    CSN=1;
    return(status);   
}
/**************************************************
函数:RX_Mode()
描述:
    这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
void RX_MODE()
{
    CE=0;
    SPI_WRITE_BUF(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
    SPI_RW_REG(WRITE_REG+EN_AA,0X01);
    SPI_RW_REG(WRITE_REG+EN_RXADDR,0X01);
    SPI_RW_REG(WRITE_REG+RF_CH,40);
    SPI_RW_REG(WRITE_REG+RX_PW_P0,TX_PLOAD_WIDTH);
    SPI_RW_REG(WRITE_REG+RF_SETUP,0X07);
    SPI_RW_REG(WRITE_REG+CONFIG,0x0f);
    CE=1;
}
/**************************************************
函数:TX_Mode()
描述:
    这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),
    130us后启动发射,数据发送结束后,发送模块自动转入接收
    模式等待应答信号。
/**************************************************/
void TX_MODE(uchar *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,BUF,TX_PLOAD_WIDTH);
    SPI_RW_REG(WRITE_REG+EN_AA,0X01);
    SPI_RW_REG(WRITE_REG+EN_RXADDR,0X01);
    SPI_RW_REG(WRITE_REG+SETUP_RETR,0X0A);
    SPI_RW_REG(WRITE_REG+RF_CH,40);
    SPI_RW_REG(WRITE_REG+RF_SETUP,0X07);
    SPI_RW_REG(WRITE_REG+CONFIG,0x0e);
    CE=1;
}
/**************************************************
函数:Check_ACK()
描述:
    检查接收设备有无接收到数据包,设定没有收到应答信
    号是否重发
/**************************************************/
uchar Check_ACK(bit clear)
{
    while(IRQ);
    sta = SPI_RW(NOP);                    // 返回状态寄存器
    if(MAX_RT)
        if(clear)                         // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发
            SPI_RW(FLUSH_TX);
    SPI_RW_REG(WRITE_REG + STATUS, sta);  // 清除TX_DS或MAX_RT中断标志
    IRQ = 1;
    if(TX_DS)
        return(0x00);
    else
        return(0xff);
}
/**************************************************
函数:keyscan()
描述:检测是否有按键按下,按下则发送一字节数据
**************************************************/
void keyscan()
{
    if(key==0)
    {
        delay(5);
        if(key==0)
        {
            TX_BUF[0]=~DATA;
            TX_MODE(TX_BUF);
            LED=~DATA;
            Check_ACK(1);
            delay(500);
            LED=0XFF;
            while(!key);
            DATA<<=1;
            if(!DATA)
                DATA=0x01;   
        }
    }
}
void main()
{
    init_io();
//    TX_MODE();
    while(1)
    {
        keyscan();   
    }
}
nRF24l01头文件
#ifndef _API_DEF_
#define _API_DEF_
// Define interface to nRF24L01
// Define SPI pins
sbit CE   = P1^0;  // Chip Enable pin signal (output)
sbit CSN  = P1^1;  // Slave Select pin, (output to CSN, nRF24L01)
sbit IRQ  = P1^3;  // Interrupt signal, from nRF24L01 (input)
sbit MISO = P1^4;  // Master In, Slave Out pin (input)
sbit MOSI = P1^5;  // Serial Clock pin, (output)
sbit SCK  = P1^7;  // Master Out, Slave In pin (output)
// SPI(nRF24L01) commands
#define READ_REG    0x00  // Define read command to register
#define WRITE_REG   0x20  // Define write command to register
#define RD_RX_PLOAD 0x61  // Define RX payload register address
#define WR_TX_PLOAD 0xA0  // Define TX payload register address
#define FLUSH_TX    0xE1  // Define flush TX register command
#define FLUSH_RX    0xE2  // Define flush RX register command
#define REUSE_TX_PL 0xE3  // Define reuse TX payload register command
#define NOP         0xFF  // Define No Operation, might be used to read status register
// SPI(nRF24L01) registers(addresses)
#define CONFIG      0x00  // 'Config' register address
#define EN_AA       0x01  // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR   0x02  // 'Enabled RX addresses' register address
#define SETUP_AW    0x03  // 'Setup address width' register address
#define SETUP_RETR  0x04  // 'Setup Auto. Retrans' register address
#define RF_CH       0x05  // 'RF channel' register address
#define RF_SETUP    0x06  // 'RF setup' register address
#define STATUS      0x07  // 'Status' register address
#define OBSERVE_TX  0x08  // 'Observe TX' register address
#define CD          0x09  // 'Carrier Detect' register address
#define RX_ADDR_P0  0x0A  // 'RX address pipe0' register address
#define RX_ADDR_P1  0x0B  // 'RX address pipe1' register address
#define RX_ADDR_P2  0x0C  // 'RX address pipe2' register address
#define RX_ADDR_P3  0x0D  // 'RX address pipe3' register address
#define RX_ADDR_P4  0x0E  // 'RX address pipe4' register address
#define RX_ADDR_P5  0x0F  // 'RX address pipe5' register address
#define TX_ADDR     0x10  // 'TX address' register address
#define RX_PW_P0    0x11  // 'RX payload width, pipe0' register address
#define RX_PW_P1    0x12  // 'RX payload width, pipe1' register address
#define RX_PW_P2    0x13  // 'RX payload width, pipe2' register address
#define RX_PW_P3    0x14  // 'RX payload width, pipe3' register address
#define RX_PW_P4    0x15  // 'RX payload width, pipe4' register address
#define RX_PW_P5    0x16  // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17  // 'FIFO Status Register' register address
#endif   /* _API_DEF_ */

这位朋友,我告你程序怎么调试。
首先排除硬件的问题,然后再修改程序。
做程序,不管多么简单,千万不要一下子把功能都写出来,要步步为营。一步一步来,看着慢,其实快。
硬件排除,89C52的P0口内部没有上拉电阻,需要外部接10K的上拉电阻,你接了吗?你写一个最简单的程序,把P0.1搞成高电平,用万用表量一下电平是不是高电平,再写一个程序把P0.1脚搞成低电平,用万用表量一下是不是低电平。
软件排除,给NRF24L01的寄存器里面写一个数据,再读出来,看看写进去的数和读出来的一样不?如果一样,再往下谈配置。如果不一样,你先搞成一样的吧,不一样,说明SPI通信都不对,更谈不上无线收发数据了。
上一步完成,你就可以配置NRF24L01了,两个NRF24L01通信需要满足的条件有:
    发射接收数据宽度相同(1~32个字节)
    发射接收地址相同(5个8位地址)
    发射接收频道相同(0~125)
    发射接收速率相同(2M 1M 250K)
看看你的是不是一样?

我曾经写过一个比较完整的NRF24L01的资料,你看看
rationmcu.com/elecjc/226.html

有加中断、加状态寄存器标志位清除吗?

其实不建议你用STC的单片机调试nrf24l01,不能仿真,我用ARM、430、飞思卡尔等单片机都写过nrf,会出现比较多问题,但是仿真调试还是方便解决的

您好 请问您做过飞思卡尔单片机吗,可以发源程序看一下吗  谢谢了937227642@qq.com

思路是对的,但是依然接收不到数据

你好  我用430单片机写无线通信的程序  也接收不到数据  能加你联系方式具体聊一下么  我QQ;191707521

能解决仿真吗?protuse一直找不到合适的封装库

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

网站地图

Top