参考了很多程序,经过测试,才看懂nrf24l01的状态机,在看数据手册时很多地方都不懂后来看了关于调试的文章
再自己测试了一下某些功能,只测试了一边发送,一边接收的功能,做的很妥跟网上的程序相差无几。
#include <REG51.H>
#include "NRF24L01.h"
#define TX_ADDR_WIDTH 5 //本地发射地址宽度
#define RX_ADDR_WIDTH 5 //本地接收地址宽度
#define TX_DATA_WIDTH 3 //发送数据字节数 最大字节数为32字节
#define RX_DATA_WIDTH 3 //接收数据字节数
unsigned char code TX_ADDRESS[TX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78}; //发射通道地址
unsigned char code RX_ADDRESS_P0[RX_ADDR_WIDTH]={0x78,0x78,0x78,0x78,0x78}; //接收通道地址
unsigned char bdata status; //定义一个位与字节都可以访问的变量用来监控IRQ中断信号
sbit RX_DR=status^6; //当接收到有效数据后变为1
sbit TX_DR=status^5; //当数据发送完成后产生中断,在自动应答模式中接收到应答信号后为1
sbit MAX_RT=status^4; //当达到最大重发次数后变为1,产生此中断后必须清零后才能再次通讯
void usdelay(void) //误差 -0.149305555556us 12us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
void usdelay130(void) //误差 -0.451388888889us
{
unsigned char a,b;
for(b=11;b>0;b--)
for(a=4;a>0;a--);
}
unsigned char SPI_RW(unsigned char uchar) //SPI协议
{
unsigned char i;
for(i=0;i<8;i++)
{
SCK=0;
MOSI=uchar&0x80; //从字节高位向NRF24L01写数据
uchar=uchar<<1;
SCK=1;
uchar=uchar|MISO; //接收从NRF24L01发过来的数据
SCK=0;
}
return uchar; //返回读取的值
}
unsigned char SPI_read(unsigned char reg) //SPI读操作 两个字节完成读一次 reg:读指令
{
unsigned char bl;
CSN=0;
SPI_RW(reg); //第一个字节写读某个寄存器的指令 此时返回值为状态寄存器的值
bl=SPI_RW(0); //第二个字节返回所需要的寄存器的值
CSN=1;
return bl;
}
unsigned char SPI_write(unsigned char reg,unsigned char value) //SPI写操作 写一个字节的数据 先写指令说明往哪个寄存器写数据,reg:指令,value:数据
{
unsigned char status;
CSN=0;
status=SPI_RW(reg); //写指令并返回状态寄存器的值
SPI_RW(value); //写数据
CSN=1;
return status; //返回状态寄存器的值
}
unsigned char SPI_read_more(unsigned char reg,unsigned char *puf_read,unsigned char width) //读取多个数据 reg:指令,*puf存储数据的指针,width:要读取数据的长度
{
unsigned char i,status;
CSN=0;
status=SPI_RW(reg); //写指令 并返回状态寄存器的值
for(i=0;i<width;i++) //循环读出数据
{
puf_read[i]=SPI_RW(0); //将循环读出的数据存储在一个数组中
}
CSN=1;
return status;
}
unsigned char SPI_write_more(unsigned char reg,unsigned char *puf_write,unsigned char width) //写多个数据 reg:指令,*puf:要写的数据,width:数据长度
{
unsigned char i,status;
CSN=0;
status=SPI_RW(reg); //写指令 并返回状态寄存器的值
for(i=0;i<width;i++) //循环写入数据
{
SPI_RW(*puf_write++);
}
CSN=1;
return status;
}
void receive_model() //接收模式初始化配置
{
CE=0; //掉电模式 此时PWR_UP为0
CSN=1; //停止寄存器读写
SCK=0; //时钟信号停止读写
IRQ=1; //中断复位
SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0,RX_ADDR_WIDTH); //写本地接收的地址
SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答
SPI_write(WRITE_REG+EN_RXADDR,0x01); //接收通道0允许
SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4G
SPI_write(WRITE_REG+RX_PW_P0,TX_DATA_WIDTH); //设置数据通道0传输数据宽度为3个字节
SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率,发射功率
SPI_write(WRITE_REG+CONFIG,0x0F); //配置寄存器,设置CRC和工作模式(接收模式)
CE=1; //启动
}
void send_model() //发射模式初始化配置
{
CE=0; //掉电模式 此时PWR_UP为0
CSN=1; //停止寄存器读写
SCK=0; //时钟信号停止读写
IRQ=1; //中断复位
SPI_write_more(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADDR_WIDTH); //写本地发射地址
SPI_write_more(WRITE_REG+RX_ADDR_P0,RX_ADDRESS_P0,RX_ADDR_WIDTH); //写本地接收(主要用来使能自动应答)
SPI_write(WRITE_REG+EN_AA,0x00); //失能自动应答功能
SPI_write(WRITE_REG+EN_RXADDR,0x00); //失能接收通道0
SPI_write(WRITE_REG+SETUP_RETR,0x00); //失能自动重发
SPI_write(WRITE_REG+RF_CH,0x00); //通信频率 2.4G
SPI_write(WRITE_REG+RX_PW_P0,RX_DATA_WIDTH); //设置接收数据长度为3个字节
SPI_write(WRITE_REG+RF_SETUP,0x09); //设置发射参数:传输速率2MHZ,发射功率
SPI_write(WRITE_REG+CONFIG,0x0e); //配置寄存器,设置CRC和工作模式(发射模式)
CE=1; //启动
}
void send_data(unsigned char *pArray) //发送数据
{
CE=0; //停止射频工作,待机模式1
// SPI_write_more(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADDR_WIDTH); //装载接收端地址 此地址单对单发送时可只初始化一次
SPI_write_more(WR_TX_PLOAD,pArray,3); //向nrf24l01传入要发送的数据
// SPI_write(WRITE_REG+CONFIG,0x0e); //IRQ收发完成中断响应,16位CRC,发送模式 此功能在但对单发送时可初始化一次
CE=1; //置高CE,激发数据
usdelay(); //10us的延时
}
unsigned char read_data(unsigned char *pArray) //读取接收的数据 *pArray:传入存放数据的数组
{
unsigned char mark;
CE=1; //接收模式
usdelay130(); //等待130us
status=SPI_read(STATUS); //读取状态寄存器的值来判断数据的接收情况
if(RX_DR==1)
{
CE=0; //接收完数据变成待机模式1
SPI_read_more(RD_RX_PLOAD,pArray,RX_DATA_WIDTH); //读取数据并将其存放在RX_DATA中
mark=1; //读取完成标志
}
SPI_write(WRITE_REG+STATUS,status); //清除中断标志位
return mark;
}
/**************************************************************************************************************/
void main()
{
unsigned char mark,i; //接收完成标志
delay(1000);
receive_model(); //接收模式初始化配置
delay(1000);
while(1)
{
mark=read_data(RX_DATA);
if(mark==1)
{
i++;
SPI_write(FLUSH_RX,0); //清空RX_FIFO 中的缓存数据 接受不像发送会自动清空缓存区的数据
if(RX_DATA[0]==0&&RX_DATA[1]==1&&RX_DATA[2]==2)
{
led0=0;
delay(100);
RX_DATA[0]=0;
RX_DATA[1]=0;
RX_DATA[2]=0;
}
mark=0;
}
SPI_read(STATUS); //读状态寄存器
SPI_read(FIFO_STATUS); //读FIFO状态
led0=1;
}
}