1、24L01+带大数据包地ACK用于双向传输发现网上关于24L01带数据包的ACK介绍的比较少,自己之前做四轴的时候想说用24L01做双向通讯,但是对于频繁切换发送、接收模式很是麻烦,时间调的不好很容易造成通讯失败,后来想到24L01的带数据包的ACK做双向通讯,在网上找了资料,但是就只做了简单介绍,没有介绍用的时候是怎么实现,下面我就对我使用的过程做一个总结,在附上测试程序(C51),本人热衷于使用STC单片机做东西,四轴也是用STC单片机来做的控制板,飞的也还行。对于初学者来讲,STC单片机的程序看起来也比较容易看得懂,对于双向传输,我看过STM32的程序,想要移植到51上,但是对于发送接收
2、部分没有详细的注释,所以刚开始也是一头雾水,找半天都找不到什么时候吧带数据的ACK包送入缓存,所以也就放弃了,但是我觉得初始化部分写的比较好,所以也就移植了部分程序,好了不多说,下面开始将原理:带数据包的ACK应答传输,有的人说只能用在24L01+上,没有+的用不了,然而我刚好只有带+的,没带+的用不用的了这个我就不知道了,但是我看过没带+的芯片手册,并没有看到有关带数据包的ACK的介绍,然后又看了带+的芯片手册,在带+的手册上发现有相关带数据包的ACK的介绍,所以我也认为ACK要能带数据包,只能用在有+的芯片上。利用这个ACK做数据传输,首先要配置正确,对于配置,你们网上找找,也能找到,我也
3、在这里直接复制粘贴别人的说法:1,需要设置成为可变长度的接收与发送2,需要将接收数据的ACK使能3,由于ACK带有数据因此自动重发的时间要改成500S4,将数据写入等待发送使用的是W_ACK_PAYLOAD命令作为接收模式,若要让ACK带上数据包,那就得在接收到数据之前,把数据包送到ACK发送缓存,将数据写入W_ACK_PAYLOAD这个地址里面,详细介绍如下从这里可以看出,W_ACK_PAYLOAD的地址为0xA8-0xAD,用哪个地址由你喜欢,缓存字节数为32字节。所以,初始化为接收模式之后,就先装载ACK包,然后在进入接收循环,每当接收到发送端发送过来的数据,读取数据完毕,马上把ACK数
4、据包再写进去,不写的话发送端就接收不到带数据包的ACK。作为发送端,在发送完数据之后立马就读取到ACK数据包了,我刚开始用的时候也是犯傻,怎么把ACK里面的数据提取出来,想了半天,后来也是灵光一现,想着,手册上说,通道0是接收应答信号的,那收到的ACK数据包读取方式应该跟一般接收到的数据读取方式是一样的,所以我就尝试了一下,果然成了,能接收到数据了,废话不多说,我文采不好,不想打这么多字了,下面直接附上程序:以下是.h文件/*/#ifndef _NRF24L01_H_#define _NRF24L01_H_#define uchar unsigned char#define uint unsi
5、gned int/*1:GND;2:Vcc;3:CE;4CSN;5:SCK;6:MOSI;7:MISO;8:IRQ*/ sbit CE = P73; / Chip Enable pin signal (output)/ sbit CSN = P72; / Slave Select pin, (output to CSN, nRF24L01)/ sbit SCK = P71; / Interrupt signal, from nRF24L01 (input)/ sbit MOSI = P70; / Master In, Slave Out pin (input)/ sbit MISO = P37
6、; / Serial Clock pin, (output)/ sbit IRQ = P36; / Master Out, Slave In pin (output)sbit CE = P04; / Chip Enable pin signal (output)sbit CSN = P03; / Slave Select pin, (output to CSN, nRF24L01)sbit SCK = P02; / Interrupt signal, from nRF24L01 (input)sbit MOSI = P01; / Master In, Slave Out pin (input)
7、sbit MISO = P00; / Serial Clock pin, (output)sbit IRQ = P46; / Master Out, Slave In pin (output)/ SPI(nRF24L01) commands#define READ_REG 0x00 /读寄存器指令#define WRITE_REG 0x20 /写寄存器指令#define R_RX_PL_WID 0x60 /读接收到的数据长度#define RD_RX_PLOAD 0x61 /读接收数据指令#define WR_TX_PLOAD 0xA0 /写待发送数据指令#define W_ACK_PAYLO
8、AD 0xA8 /写ACK数据指令,用于接收模式#define FLUSH_TX 0xE1 /冲洗发送FIFO指令#define FLUSH_RX 0xE2 /冲洗接收FIFO指令#define REUSE_TX_PL 0xE3 /重复装载数据指令#define NOP 0xFF /空指令,用于读出状态字/寄存器地址#define CONFIG 0x00 /配置寄存器#define EN_AA 0x01 /自动应答,禁止自动应答后可以与2401通讯#define EN_RXADDR 0x02 /接收地址允许#define SETUP_AW 0x03 /设置地址宽度#define SETUP_R
9、ETR 0x04 /自动重发#define RF_CH 0x05 /射频通道#define RF_SETUP 0x06 /射频寄存器#define STATUS 0x07 /状态寄存器#define OBSERVE_TX 0x08 /发送检测寄存器#define CD 0x09 /地址检查#define RX_ADDR_P0 0x0A /数据通道0接收地址,最大长度5个字节,先写低字节,所有字节数量由SETUP_AW设定#define RX_ADDR_P1 0x0B /数据通道1接收地址,最大长度5个字节,先写低字节,所有字节数量由SETUP_AW设定#define RX_ADDR_P2 0x
10、0C /数据通道2接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P139:8相等#define RX_ADDR_P3 0x0D /数据通道3接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P139:8相等#define RX_ADDR_P4 0x0E /数据通道4接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P139:8相等#define RX_ADDR_P5 0x0F /数据通道5接收地址,最低字节可设定,高字节部分必须与RX_ADDR_P139:8相等#define TX_ADDR 0x10 /发送地址#define RX_PW_P0 0x11 /通道0接
11、收数据长度#define RX_PW_P1 0x12 /通道1接收数据长度#define RX_PW_P2 0x13 /通道2接收数据长度#define RX_PW_P3 0x14 /通道3接收数据长度#define RX_PW_P4 0x15 /通道4接收数据长度#define RX_PW_P5 0x16 /通道5接收数据长度#define FIFO_STATUS 0x17 /FIFO状态寄存器#define DYNPD 0x1C#define FEATURE 0x1D#define Mode_RX1 1 /普通接收模式#define Mode_TX1 2 /普通发送模式#define Mo
12、de_RX2 3 /双向传输接收模式#define Mode_TX2 4 /双向传输发送模式#define TX_ADR_WIDTH 5 / 5字节宽度的发送地址#define RX_ADR_WIDTH 5 / 5字节宽度的接收地址#define TX_PLOAD_WIDTH 32 / 数据通道有效数据宽度#define RX_PLOAD_WIDTH 32 / 数据通道有效数据宽度extern uchar code TX_ADDRESSTX_ADR_WIDTH;extern uchar code RX_ADDRESSRX_ADR_WIDTH;extern uchar RX_BUFTX_PLOA
13、D_WIDTH; /接收缓存extern uchar TX_BUFTX_PLOAD_WIDTH; /发送缓存extern uchar RX_flag; /接收标志extern uchar Length; /数据长度void Init_24L01(Byte ModeDat,Byte ch); /初始化24L01void Delay12us();uchar SPI_RW(uchar byte); /SPI读写函数uchar SPI_Write_Reg(uchar reg, uchar value);uchar SPI_Read(uchar reg);uchar SPI_Read_Buf(uchar
14、 reg, uchar * pBuf, uchar bytes);uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes);void NRF_TX(uchar *pBuf, uchar Len); /发送数据包,用于发送模式2/4void NRF_TX_AP(uchar *pBuf, uchar Len); /发送数据包,接收模式2uchar Check_ACK(bit clear);void Read_24L01_data(void); #endif /*/以下是.c文件#include #include nrf24l01.h#inc
15、lude #include uart1.huchar bdata sta;sbit RX_DR = sta6;sbit TX_DS = sta5;sbit MAX_RT = sta4;uchar code TX_ADDRESSTX_ADR_WIDTH = 0x13,0x14,0x52,0x05,0x20; / 定义一个静态发送地址uchar code RX_ADDRESSRX_ADR_WIDTH = 0x13,0x14,0x52,0x05,0x20; / 定义一个静态发送地址uchar RX_BUFTX_PLOAD_WIDTH; /接收缓存uchar TX_BUFTX_PLOAD_WIDTH;
16、 /发送缓存uchar RX_flag; /接收标志uchar Length; /数据长度/*/*函数: init_io()描述: 初始化IO/*/void Init_24L01(Byte ModeDat,Byte ch) 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_AD
17、DR_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(
18、WRITE_REG + RF_SETUP, 0x0f); / 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 switch(ModeDat) case 1: SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); / 接收通道0选择和发送通道相同有效数据宽度 SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f); break; case 2: SPI_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); SPI_Write_Reg(WRITE_REG + CONFIG,
19、0x0e); break; case 3: 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; case 4: SPI_Write_Reg(WRITE_REG + CONFIG,
20、 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毫秒/*/void Delay12us() /18.432MHz unsigned char i;
21、_nop_(); _nop_(); _nop_(); i = 52; while (-i);/*/*函数:SPI_RW()描述: 根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/*/uchar SPI_RW(uchar byte) uchar i; for(i=0; i8; i+) / 循环8次 MOSI = (byte & 0x80); / byte最高位输出到MOSI byte = 1; / 低一位移位到最高位 SCK = 1; / 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 byte |= MISO; / 读MISO
22、到byte最低位 SCK = 0; / SCK置低 return(byte); / 返回读出的一字节/*/*函数:SPI_RW_Reg()描述: 写数据value到reg寄存器/*/uchar SPI_Write_Reg(uchar reg, uchar value) uchar status; CSN = 0; / CSN置低,开始传输数据 status = SPI_RW(reg); / 选择寄存器,同时返回状态字 SPI_RW(value); / 然后写数据到该寄存器 CSN = 1; / CSN拉高,结束数据传输 return(status); / 返回状态寄存器/*/*函数:SPI_R
23、ead()描述: 从reg寄存器读一字节/*/uchar SPI_Read(uchar reg) uchar reg_val; CSN = 0; / CSN置低,开始传输数据 SPI_RW(reg); / 选择寄存器 reg_val = SPI_RW(0); / 然后从该寄存器读数据 CSN = 1; / CSN拉高,结束数据传输 return(reg_val); / 返回寄存器数据/*/*函数:SPI_Read_Buf()描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道 数据或接收/发送地址/*/uchar SPI_Read_Buf(uchar reg, uchar * pB
24、uf, uchar bytes) uchar status, i; CSN = 0; / CSN置低,开始传输数据 status = SPI_RW(reg); / 选择寄存器,同时返回状态字 for(i=0; ibytes; i+) pBufi = SPI_RW(0); / 逐个字节从nRF24L01读出 CSN = 1; / CSN拉高,结束数据传输 return(status); / 返回状态寄存器/*/*函数:SPI_Write_Buf()描述: 把pBuf缓存中的数据写入到nRF24L01,通常用来写入发 射通道数据或接收/发送地址/*/uchar SPI_Write_Buf(ucha
25、r reg, uchar * pBuf, uchar bytes) uchar status, i; CSN = 0; / CSN置低,开始传输数据 status = SPI_RW(reg); / 选择寄存器,同时返回状态字 for(i=0; ibytes; i+) SPI_RW(pBufi); / 逐个字节写入nRF24L01 CSN = 1; / CSN拉高,结束数据传输 return(status); / 返回状态寄存器/*/void NRF_TX(uchar *pBuf, uchar Len) /发送数据包,用于发送模式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();void NRF_TX_AP(uchar *pBuf, uchar Len) /发送数据包,接收模式2
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1