24L01+带大数据包地ACK用于双向传输.docx
- 文档编号:9345634
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:19
- 大小:54.98KB
24L01+带大数据包地ACK用于双向传输.docx
《24L01+带大数据包地ACK用于双向传输.docx》由会员分享,可在线阅读,更多相关《24L01+带大数据包地ACK用于双向传输.docx(19页珍藏版)》请在冰豆网上搜索。
24L01+带大数据包地ACK用于双向传输
发现网上关于24L01带数据包的ACK介绍的比较少,自己之前做四轴的时候想说用24L01做双向通讯,但是对于频繁切换发送、接收模式很是麻烦,时间调的不好很容易造成通讯失败,后来想到24L01的带数据包的ACK做双向通讯,在网上找了资料,但是就只做了简单介绍,没有介绍用的时候是怎么实现,下面我就对我使用的过程做一个总结,在附上测试程序(C51),本人热衷于使用STC单片机做东西,四轴也是用STC单片机来做的控制板,飞的也还行。
对于初学者来讲,STC单片机的程序看起来也比较容易看得懂,对于双向传输,我看过STM32的程序,想要移植到51上,但是对于发送接收部分没有详细的注释,所以刚开始也是一头雾水,找半天都找不到什么时候吧带数据的ACK包送入缓存,所以也就放弃了,但是我觉得初始化部分写的比较好,所以也就移植了部分程序,好了不多说,下面开始将原理:
带数据包的ACK应答传输,有的人说只能用在24L01+上,没有+的用不了,然而我刚好只有带+的,没带+的用不用的了这个我就不知道了,但是我看过没带+的芯片手册,并没有看到有关带数据包的ACK的介绍,然后又看了带+的芯片手册,在带+的手册上发现有相关带数据包的ACK的介绍,所以我也认为ACK要能带数据包,只能用在有+的芯片上。
利用这个ACK做数据传输,首先要配置正确,对于配置,你们网上找找,也能找到,我也在这里直接复制粘贴别人的说法:
1,需要设置成为可变长度的接收与发送
2,需要将接收数据的ACK使能
3,由于ACK带有数据因此自动重发的时间要改成500μS
4,将数据写入等待发送使用的是W_ACK_PAYLOAD命令
作为接收模式,若要让ACK带上数据包,那就得在接收到数据之前,把数据包送到ACK发送缓存,将数据写入W_ACK_PAYLOAD这个地址里面,详细介绍如下
从这里可以看出,W_ACK_PAYLOAD的地址为0xA8-0xAD,用哪个地址由你喜欢,缓存字节数为32字节。
所以,初始化为接收模式之后,就先装载ACK包,然后在进入接收循环,每当接收到发送端发送过来的数据,读取数据完毕,马上把ACK数据包再写进去,不写的话发送端就接收不到带数据包的ACK。
作为发送端,在发送完数据之后立马就读取到ACK数据包了,我刚开始用的时候也是犯傻,怎么把ACK里面的数据提取出来,想了半天,后来也是灵光一现,想着,手册上说,通道0是接收应答信号的,那收到的ACK数据包读取方式应该跟一般接收到的数据读取方式是一样的,所以我就尝试了一下,果然成了,能接收到数据了,废话不多说,我文采不好,不想打这么多字了,下面直接附上程序:
以下是.h文件
/*****************************************************************************************************************************************************/
#ifndef__NRF24L01_H_
#define__NRF24L01_H_
#defineucharunsignedchar
#defineuintunsignedint
/*
1:
GND;2:
Vcc;3:
CE;4CSN;5:
SCK;6:
MOSI;7:
MISO;8:
IRQ
*/
//sbitCE=P7^3;//ChipEnablepinsignal(output)
//sbitCSN=P7^2;//SlaveSelectpin,(outputtoCSN,nRF24L01)
//sbitSCK=P7^1;//Interruptsignal,fromnRF24L01(input)
//sbitMOSI=P7^0;//MasterIn,SlaveOutpin(input)
//sbitMISO=P3^7;//SerialClockpin,(output)
//sbitIRQ=P3^6;//MasterOut,SlaveInpin(output)
sbitCE=P0^4;//ChipEnablepinsignal(output)
sbitCSN=P0^3;//SlaveSelectpin,(outputtoCSN,nRF24L01)
sbitSCK=P0^2;//Interruptsignal,fromnRF24L01(input)
sbitMOSI=P0^1;//MasterIn,SlaveOutpin(input)
sbitMISO=P0^0;//SerialClockpin,(output)
sbitIRQ=P4^6;//MasterOut,SlaveInpin(output)
//SPI(nRF24L01)commands
#defineREAD_REG0x00//读寄存器指令
#defineWRITE_REG0x20//写寄存器指令
#defineR_RX_PL_WID0x60//读接收到的数据长度
#defineRD_RX_PLOAD0x61//读接收数据指令
#defineWR_TX_PLOAD0xA0//写待发送数据指令
#defineW_ACK_PAYLOAD0xA8//写ACK数据指令,用于接收模式
#defineFLUSH_TX0xE1//冲洗发送FIFO指令
#defineFLUSH_RX0xE2//冲洗接收FIFO指令
#defineREUSE_TX_PL0xE3//重复装载数据指令
#defineNOP0xFF//空指令,用于读出状态字
//寄存器地址
#defineCONFIG0x00//配置寄存器
#defineEN_AA0x01//自动应答,禁止自动应答后可以与2401通讯
#defineEN_RXADDR0x02//接收地址允许
#defineSETUP_AW0x03//设置地址宽度
#defineSETUP_RETR0x04//自动重发
#defineRF_CH0x05//射频通道
#defineRF_SETUP0x06//射频寄存器
#defineSTATUS0x07//状态寄存器
#defineOBSERVE_TX0x08//发送检测寄存器
#defineCD0x09//地址检查
#defineRX_ADDR_P00x0A//数据通道0接收地址,最大长度5个字节,先写低字节,所有字节数量由SETUP_AW设定
#defineRX_ADDR_P10x0B//数据通道1接收地址,最大长度5个字节,先写低字节,所有字节数量由SETUP_AW设定
#defineRX_ADDR_P20x0C//数据通道2接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P1[39:
8]相等
#defineRX_ADDR_P30x0D//数据通道3接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P1[39:
8]相等
#defineRX_ADDR_P40x0E//数据通道4接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P1[39:
8]相等
#defineRX_ADDR_P50x0F//数据通道5接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P1[39:
8]相等
#defineTX_ADDR0x10//发送地址
#defineRX_PW_P00x11//通道0接收数据长度
#defineRX_PW_P10x12//通道1接收数据长度
#defineRX_PW_P20x13//通道2接收数据长度
#defineRX_PW_P30x14//通道3接收数据长度
#defineRX_PW_P40x15//通道4接收数据长度
#defineRX_PW_P50x16//通道5接收数据长度
#defineFIFO_STATUS0x17//FIFO状态寄存器
#defineDYNPD0x1C
#defineFEATURE0x1D
#defineMode_RX11//普通接收模式
#defineMode_TX12//普通发送模式
#defineMode_RX23//双向传输接收模式
#defineMode_TX24//双向传输发送模式
#defineTX_ADR_WIDTH5//5字节宽度的发送地址
#defineRX_ADR_WIDTH5//5字节宽度的接收地址
#defineTX_PLOAD_WIDTH32//数据通道有效数据宽度
#defineRX_PLOAD_WIDTH32//数据通道有效数据宽度
externucharcodeTX_ADDRESS[TX_ADR_WIDTH];
externucharcodeRX_ADDRESS[RX_ADR_WIDTH];
externucharRX_BUF[TX_PLOAD_WIDTH];//接收缓存
externucharTX_BUF[TX_PLOAD_WIDTH];//发送缓存
externucharRX_flag;//接收标志
externucharLength;//数据长度
voidInit_24L01(ByteModeDat,Bytech);//初始化24L01
voidDelay12us();
ucharSPI_RW(ucharbyte);//SPI读写函数
ucharSPI_Write_Reg(ucharreg,ucharvalue);
ucharSPI_Read(ucharreg);
ucharSPI_Read_Buf(ucharreg,uchar*pBuf,ucharbytes);
ucharSPI_Write_Buf(ucharreg,uchar*pBuf,ucharbytes);
voidNRF_TX(uchar*pBuf,ucharLen);//发送数据包,用于发送模式2/4
voidNRF_TX_AP(uchar*pBuf,ucharLen);//发送数据包,接收模式2
ucharCheck_ACK(bitclear);
voidRead_24L01_data(void);
#endif
/********************************************************************************************************************************************************/
以下是.c文件
#include
#include"nrf24l01.h"
#include
#include"uart1.h"
ucharbdatasta;
sbitRX_DR=sta^6;
sbitTX_DS=sta^5;
sbitMAX_RT=sta^4;
ucharcodeTX_ADDRESS[TX_ADR_WIDTH]={0x13,0x14,0x52,0x05,0x20};//定义一个静态发送地址
ucharcodeRX_ADDRESS[RX_ADR_WIDTH]={0x13,0x14,0x52,0x05,0x20};//定义一个静态发送地址
ucharRX_BUF[TX_PLOAD_WIDTH];//接收缓存
ucharTX_BUF[TX_PLOAD_WIDTH];//发送缓存
ucharRX_flag;//接收标志
ucharLength;//数据长度
/**************************************************/
/**************************************************
函数:
init_io()
描述:
初始化IO
/**************************************************/
voidInit_24L01(ByteModeDat,Bytech)
{
CE=0;//待机
CSN=1;//SPI禁止
SCK=0;//SPI时钟置低
IRQ=1;//中断复位
Delay12us();
CE=0;
SPI_Write_Buf(WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);//写入发送地址
SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//为了应答接收设备,接收通道0地址和发送地址相同
SPI_Write_Reg(WRITE_REG+EN_AA,0x01);//使能接收通道0自动应答
SPI_Write_Reg(WRITE_REG+EN_RXADDR,0x01);//使能接收通道0
SPI_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//自动重发延时等待500us,自动重发10次
SPI_Write_Reg(WRITE_REG+RF_CH,ch);//选择射频通道ch
SPI_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
switch(ModeDat)
{
case1:
SPI_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//接收通道0选择和发送通道相同有效数据宽度
SPI_Write_Reg(WRITE_REG+CONFIG,0x0f);
break;
case2:
SPI_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG+CONFIG,0x0e);
break;
case3:
SPI_Write_Reg(FLUSH_TX,0xff);
SPI_Write_Reg(FLUSH_RX,0xff);
SPI_Write_Reg(WRITE_REG+CONFIG,0x0f);//IRQ收发完成中断开启,16位CRC,主接收
SPI_RW(0x50);
SPI_RW(0x73);
SPI_Write_Reg(WRITE_REG+DYNPD,0x01);
SPI_Write_Reg(WRITE_REG+FEATURE,0x06);
break;
case4:
SPI_Write_Reg(WRITE_REG+CONFIG,0x0e);//IRQ收发完成中断开启,16位CRC,主发送
SPI_Write_Reg(FLUSH_TX,0xff);
SPI_Write_Reg(FLUSH_RX,0xff);
SPI_RW(0x50);
SPI_RW(0x73);
SPI_Write_Reg(WRITE_REG+DYNPD,0x01);
SPI_Write_Reg(WRITE_REG+FEATURE,0x06);
break;
default:
break;
}
CE=1;
}
/**************************************************/
/**************************************************
函数:
delay_ms()
描述:
延迟x毫秒
/**************************************************/
voidDelay12us()//@18.432MHz
{
unsignedchari;
_nop_();
_nop_();
_nop_();
i=52;
while(--i);
}
/**************************************************/
/**************************************************
函数:
SPI_RW()
描述:
根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
读出一字节
/**************************************************/
ucharSPI_RW(ucharbyte)
{
uchari;
for(i=0;i<8;i++)//循环8次
{
MOSI=(byte&0x80);//byte最高位输出到MOSI
byte<<=1;//低一位移位到最高位
SCK=1;//拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
byte|=MISO;//读MISO到byte最低位
SCK=0;//SCK置低
}
return(byte);//返回读出的一字节
}
/**************************************************/
/**************************************************
函数:
SPI_RW_Reg()
描述:
写数据value到reg寄存器
/**************************************************/
ucharSPI_Write_Reg(ucharreg,ucharvalue)
{
ucharstatus;
CSN=0;//CSN置低,开始传输数据
status=SPI_RW(reg);//选择寄存器,同时返回状态字
SPI_RW(value);//然后写数据到该寄存器
CSN=1;//CSN拉高,结束数据传输
return(status);//返回状态寄存器
}
/**************************************************/
/**************************************************
函数:
SPI_Read()
描述:
从reg寄存器读一字节
/**************************************************/
ucharSPI_Read(ucharreg)
{
ucharreg_val;
CSN=0;//CSN置低,开始传输数据
SPI_RW(reg);//选择寄存器
reg_val=SPI_RW(0);//然后从该寄存器读数据
CSN=1;//CSN拉高,结束数据传输
return(reg_val);//返回寄存器数据
}
/**************************************************/
/**************************************************
函数:
SPI_Read_Buf()
描述:
从reg寄存器读出bytes个字节,通常用来读取接收通道
数据或接收/发送地址
/**************************************************/
ucharSPI_Read_Buf(ucharreg,uchar*pBuf,ucharbytes)
{
ucharstatus,i;
CSN=0;//CSN置低,开始传输数据
status=SPI_RW(reg);//选择寄存器,同时返回状态字
for(i=0;i pBuf[i]=SPI_RW(0);//逐个字节从nRF24L01读出 CSN=1;//CSN拉高,结束数据传输 return(status);//返回状态寄存器 } /**************************************************/ /************************************************** 函数: SPI_Write_Buf() 描述: 把pBuf缓存中的数据写入到nRF24L01,通常用来写入发 射通道数据或接收/发送地址 /**************************************************/ ucharSPI_Write_Buf(ucharreg,uchar*pBuf,ucharbytes) { ucharstatus,i; CSN=0;//CSN置低,开始传输数据 status=SPI_RW(reg);//选择寄存器,同时返回状态字 for(i=0;i SPI_RW(pBuf[i]);//逐个字节写入nRF24L01 CSN=1;//CSN拉高,结束数据传输 return(status);//返回状态寄存器 } /**************************************************/ voidNRF_TX(uchar*pBuf,ucharLen)//发送数据包,用于发送模式2/4 { CE=0; SPI_Write_Buf(WRITE_REG+RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);//装载接收端地址 SPI_Write_Buf(WR_TX_PLOAD,pBuf,Len);//装载数据 CE=1; Delay12us(); } voidNRF_TX_AP(uchar*pBuf,ucharLen)//发送数据包,接收模式2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 24 L01 数据包 ACK 用于 双向 传输