求助:nrf24l01无法实现通信,急求答案~~~~
接收端程序:
#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一直找不到合适的封装库