nrf24l01的调试测试程序

参考了很多程序,经过测试,才看懂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;
}
}



一、测试距离 0.软件为Keil5,不知道是否支持Keil4(如不行请手动新建Keil4工程) 1.单片机为STM32F103C8,采用硬件SPI 2.nRF24L01+采用3.3V供电,接线如下:       24L01+       STM32 CE   ——   PA3 CS   ——   PA4 SCK  ——   PA5 MISO ——   PA6 MOSI ——   PA7   IRQ未接(采用查询方式,如须用自加外部中断程序) 3.led灯为PC13控制,低电平亮(在User\led.c中修改GPIO);按键为PA0,按下后(接地)才开始发送,默认注释了,如需要可在程序中加上 4.My24L01_Tx为发送端程序,My24L01_Rx为接收端程序; 5.发送端约100ms发送一次,不要ACK;接收端每接收到一次led反转;将程序下载到单片机后可看到接收端led快速闪动,可将接收端的24L01在一定范围内走动,若led闪动变慢,则说明有丢包;led不闪,说明没有收到数据;因此大致可测得发送距离 6.24L01采用0频道,2Mbps, 0dBm, Address 3Bytes,实测距离大于10米(在不同的房间) 二、测试速率 0.软件为Keil5,不知道是否支持Keil4(如不行请手动新建Keil4工程) 
1.单片机为STM32F103C8,采用硬件SPI
 2.nRF24L01+采用3.3V供电,接线如下:
      24L01+       STM32
 CE   ——   PA3
 CS   ——   PA4
 SCK  ——   PA5
 MISO ——   PA6
 MOSI ——   PA7  
 IRQ未接(采用查询方式,如须用自加外部中断程序) 

3.led灯为PC13控制,低电平亮(在User\led.c中修改GPIO);按键为PA0,按下后(接地)才开始发送!!! 

4.My24L01_Tx为发送端程序,My24L01_Rx为接收端程序;

 5.接收端先上电,发送端上电后按下按键后才发送50KB(32B一帧 共32*50帧 32*32=1024=1K),发送端收到ACK后才发下一帧,发完后进入死循环,如须再发要先复位或重新上电;接收端每收到一次led反转;(如未反转说明未成功发送,发送端接收端重新复位后再试)时间可看在接收程序中tim3Count(单位ms 16进制,定时器1ms中断)在Watch1中

 6.发送端我用的是延时等待查询STATUS寄存器,用外部中断IRQ应该会更好(未测试) 

7.24L01采用0频道,2Mbps, 0dBm, Address 3Bytes,实测速率约为50KB/s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值