最近在准备9月份的电子设计大赛,这几天没什么事,就写了一些模块的驱动。今天学习了一下无线模块NRF24L01,由于手上有好几块原子的STM32的板子,于是首先参考了一下原子的程序,然后又看了一下NRF24L01的资料,现在把心得和体会记录下来。
一、模块介绍
(1) 2.4Ghz 全球开放ISM 频段免许可证使用
(2) 最高工作速率2Mbps,高效GFSK调制,抗干扰能力强,特别适合工业控制场合
(3) 126 频道,满足多点通信和跳频通信需要
(4) 内置硬件CRC 检错和点对多点通信地址控制
(5) 低功耗1.9 - 3.6V 工作,待机模式下状态为22uA;掉电模式下为900nA
(6) 内置2.4Ghz 天线,体积种类多样
(7) 模块可软件设地址,只有收到本机地址时才会输出数据(提供中断指示),可直接接各种单片机使用,软件编程非常方便
(8) 内置专门稳压电路,使用各种电源包括DC/DC 开关电源均有很好的通信效果
(9) 2.54MM间距接口,DIP封装
(10)工作于Enhanced ShockBurst 具有Automatic packethandling, Auto packet transaction handling,具有可选的内置包应答机制,极大的降低丢包率。
(11)与51系列单片机P0口连接时候,需要加10K的上拉电阻,与其余口连接不需要。
(12)其他系列的单片机,如果是5V的,请参考该系列单片机IO口输出电流大小,如果超过10mA,需要串联电阻分压,否则容易烧毁模块! 如果是3.3V的,可以直接和RF24l01模块的IO口线连接。比如AVR系列单片机如果是5V 的,一般串接2K 的电阻。
二、驱动编写
NRF24L01是通过SPI总线跟单片机进行通信的,所以首先需要先编写SPI的驱动。
根据SPI协议可以采用IO口模拟,由于我使用的STM32F103带有SPI外设,结合库函数设置SPI,起初始化函数如下:
void SPIx_Init(void)
{
u8 SPIx_ReadWriteByte(u8 TxData);
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //ÉèÖÃSPIµ¥Ïò»òÕßË«ÏòµÄÊý¾Ýģʽ:SPIÉèÖÃΪ˫ÏßË«ÏòÈ«Ë«¹¤
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //ÉèÖÃSPI¹¤×÷ģʽ:ÉèÖÃΪÖ÷SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //ÉèÖÃSPIµÄÊý¾Ý´óС:SPI·¢ËͽÓÊÕ8λ֡½á¹¹
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //Ñ¡ÔñÁË´®ÐÐʱÖÓµÄÎÈ̬:ʱÖÓÐü¿ÕµÍµçƽ
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //Êý¾Ý²¶»ñÓÚµÚÒ»¸öʱÖÓÑØ
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSSÐźÅÓÉÓ²¼þ£¨NSS¹Ü½Å£©»¹ÊÇÈí¼þ£¨Ê¹ÓÃSSI룩¹ÜÀí:ÄÚ²¿NSSÐźÅÓÐSSIλ¿ØÖÆ
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //¶¨Ò岨ÌØÂÊÔ¤·ÖƵµÄÖµ:²¨ÌØÂÊÔ¤·ÖƵֵΪ256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //Ö¸¶¨Êý¾Ý´«Êä´ÓMSBλ»¹ÊÇLSBλ¿ªÊ¼:Êý¾Ý´«Êä´ÓMSBλ¿ªÊ¼
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRCÖµ¼ÆËãµÄ¶àÏîʽ
SPI_Init(SPI1, &SPI_InitStructure); //¸ù¾ÝSPI_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèSPIx¼Ä´æÆ÷
SPI_Cmd(SPI1, ENABLE); //ʹÄÜSPIÍâÉè
SPIx_ReadWriteByte(0xff);//Æô¶¯´«Êä
}
这里是对SPI的IO口进行初始化,以及SPI的初始设置,包括SPI数据传输模式,主从模式,SPI数据大小等。
下面要实现SPI的读/写函数,注意,这个函数是在一次操作中先发送一个字节数据,然后再读取一字节数组。
u8 SPIx_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //¼ì²éÖ¸¶¨µÄSPI±ê־λÉèÖÃÓë·ñ:·¢ËÍ»º´æ¿Õ±ê־λ
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, TxData); //ͨ¹ýÍâÉèSPIx·¢ËÍÒ»¸öÊý¾Ý
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //¼ì²éÖ¸¶¨µÄSPI±ê־λÉèÖÃÓë·ñ:½ÓÊÜ»º´æ·Ç¿Õ±ê־λ
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1); //·µ»Øͨ¹ýSPIx×î½ü½ÓÊÕµÄÊý¾Ý
}
这是最基本的函数,完成GPIO 模拟SPI 的功能。将输出字节(MOSI)从MSB 循环输出,同时将输入字节(MISO)从LSB 循环移入。上升沿读入,下降沿输出。(从SCK 被初始化为低电平可以判断出)。
SPI基本接口函数完成了,下面就可以编写NRF24L01的驱动了,首先写 写寄存器函数
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
u8 status;
Clr_NRF24L01_CSN; //ʹÄÜSPI´«Êä
status =SPIx_ReadWriteByte(reg);//·¢ËͼĴæÆ÷ºÅ
SPIx_ReadWriteByte(value); //дÈë¼Ä´æÆ÷µÄÖµ
Set_NRF24L01_CSN; //½ûÖ¹SPI´«Êä
return(status); //·µ»Ø״ֵ̬
}
这里CSN为使用端,每次对NRF24L01操作前都得先使能,即拉低,操作完成后,再失能。
然后发送要写入的寄存器地址,注意,这里寄存器地址的规则为:0x20+寄存器地址 0x20表示该寄存器地址是要写入的。
写入地址后,读取返回值,然后再将需要写入的数据写入。
下面是读寄存器函数
u8 NRF24L01_Read_Reg(u8 reg)
{
u8 reg_val;
Clr_NRF24L01_CSN; //ʹÄÜSPI´«Êä
SPIx_ReadWriteByte(reg); //·¢ËͼĴæÆ÷ºÅ
reg_val=SPIx_ReadWriteByte(0XFF);//¶ÁÈ¡¼Ä´æÆ÷ÄÚÈÝ
Set_NRF24L01_CSN; //½ûÖ¹SPI´«Êä
return(reg_val); //·µ»Ø״ֵ̬
}
其基本思路和写寄存器差不多,也需要先写入要读取的寄存器地址,读寄存器地址的命名规则为:0x00+要读取的寄存器地址。
写入地址后,不读取返回值,然后再调用SPI读/写函数,其中写入的数据随便写,因为根本就不会被写入对应寄存器,我们需要的只是其返回值,这个就是我们要读取的寄存器数据。
NRF24L01支持写入一次寄存器地址,连续多次写入或读取数据,所以我们可以写出如下一次写入或读取多字节数据的函数
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 status,u8_ctr;
Clr_NRF24L01_CSN; //ʹÄÜSPI´«Êä
status=SPIx_ReadWriteByte(reg);//·¢ËͼĴæÆ÷Öµ(λÖÃ),²¢¶Áȡ״ֵ̬
for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPIx_ReadWriteByte(0XFF);//¶Á³öÊý¾Ý
Set_NRF24L01_CSN; //¹Ø±ÕSPI´«Êä
return status; //·µ»Ø¶Áµ½µÄ״ֵ̬
}
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,u8_ctr;
Clr_NRF24L01_CSN; //ʹÄÜSPI´«Êä
status = SPIx_ReadWriteByte(reg);//·¢ËͼĴæÆ÷Öµ(λÖÃ),²¢¶Áȡ״ֵ̬
for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPIx_ReadWriteByte(*pBuf++); //дÈëÊý¾Ý
Set_NRF24L01_CSN; //¹Ø±ÕSPI´«Êä
return status; //·µ»Ø¶Áµ½µÄ״ֵ̬
}
这两个函数主要用于连续向Tx_FIFO发送数据或者从RX_FIFO读取数据。
下面编写发送一次数据的函数
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 sta;
SPIx_SetSpeed(SPI_BaudRatePrescaler_8);//spiËÙ¶ÈΪ9Mhz£¨24L01µÄ×î´óSPIʱÖÓΪ10Mhz£©
Clr_NRF24L01_CE;
NRF24L01_Write_Buf(NRF24L01_WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//дÊý¾Ýµ½TX BUF 32¸ö×Ö½Ú
Set_NRF24L01_CE;//Æô¶¯·¢ËÍ
while(NRF24L01_IRQ!=0);//µÈ´ý·¢ËÍÍê³É
sta=NRF24L01_Read_Reg(STATUS); //¶Áȡ״̬¼Ä´æÆ÷µÄÖµ
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖ¾
if(sta&MAX_TX)//´ïµ½×î´óÖØ·¢´ÎÊý
{
NRF24L01_Write_Reg(NRF24L01_FLUSH_TX,0xff);//Çå³ýTX FIFO¼Ä´æÆ÷
return MAX_TX;
}
if(sta&TX_OK)//·¢ËÍÍê³É
{
return TX_OK;
}
return 0xff;//ÆäËûÔÒò·¢ËÍʧ°Ü
}
首先将CE拉低,然后将要发送的数据送入Tx_FIFO中,再将CE拉高,启动发送。然后通过读取状态寄存器,获取发送结果。
接受一次数据的函数
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 sta;
SPIx_SetSpeed(SPI_BaudRatePrescaler_8); //spiËÙ¶ÈΪ9Mhz£¨24L01µÄ×î´óSPIʱÖÓΪ10Mhz£©
sta=NRF24L01_Read_Reg(STATUS); //¶Áȡ״̬¼Ä´æÆ÷µÄÖµ
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖ¾
if(sta&RX_OK)//½ÓÊÕµ½Êý¾Ý
{
NRF24L01_Read_Buf(NRF24L01_RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//¶ÁÈ¡Êý¾Ý
NRF24L01_Write_Reg(NRF24L01_FLUSH_RX,0xff);//Çå³ýRX FIFO¼Ä´æÆ÷
return 0;
}
return 1;//ûÊÕµ½ÈκÎÊý¾Ý
}
首先通过读取状态寄存器数据,看是否收到数据,若收到数据,则将其从Rx_FIFO中读出存入数组中,然后再清楚Rx_FIFO缓存。
最后的两个函数就是设置NRF24L01的模式,是接收模式还是发送模式。NRF24L01的模式不止这两张,其他的模式暂时没有用到,不做介绍
void RX_Mode(void)
{
Clr_NRF24L01_CE;
NRF24L01_Write_Buf(NRF24L01_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//дRX½ÚµãµØÖ·
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_AA,0x01); //ʹÄÜͨµÀ0µÄ×Ô¶¯Ó¦´ð
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_RXADDR,0x01);//ʹÄÜͨµÀ0µÄ½ÓÊÕµØÖ·
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_CH,40); //ÉèÖÃRFͨÐÅƵÂÊ
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//Ñ¡ÔñͨµÀ0µÄÓÐЧÊý¾Ý¿í¶È
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_SETUP,0x0f);//ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒ濪Æô
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+CONFIG, 0x0f);//ÅäÖûù±¾¹¤×÷ģʽµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕģʽ
Set_NRF24L01_CE; //CEΪ¸ß,½øÈë½ÓÊÕģʽ
}
void TX_Mode(void)
{
Clr_NRF24L01_CE;
NRF24L01_Write_Buf(NRF24L01_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//дTX½ÚµãµØÖ·
NRF24L01_Write_Buf(NRF24L01_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //ÉèÖÃTX½ÚµãµØÖ·,Ö÷ҪΪÁËʹÄÜACK
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_AA,0x01); //ʹÄÜͨµÀ0µÄ×Ô¶¯Ó¦´ð
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_RXADDR,0x01); //ʹÄÜͨµÀ0µÄ½ÓÊÕµØÖ·
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+SETUP_RETR,0x1a);//ÉèÖÃ×Ô¶¯ÖØ·¢¼ä¸ôʱ¼ä:500us + 86us;×î´ó×Ô¶¯ÖØ·¢´ÎÊý:10´Î
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_CH,40); //ÉèÖÃRFͨµÀΪ40
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_SETUP,0x0f); //ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒ濪Æô
NRF24L01_Write_Reg(NRF24L01_WRITE_REG+CONFIG,0x0e); //ÅäÖûù±¾¹¤×÷ģʽµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕģʽ,¿ªÆôËùÓÐÖжÏ
Set_NRF24L01_CE;//CEΪ¸ß,10usºóÆô¶¯·¢ËÍ
}
到这里,NRF24L01驱动就完成了,只要先进行模式设置(Tx_Mode或者Rx_Mode),然后调用发送或者接收函数就可以了,注意一次发送和接收的数据最多不能超过32字节。
下面是头文件中一些寄存器地址和命令的定义
//
//NRF24L01¼Ä´æÆ÷²Ù×÷ÃüÁî
#define NRF24L01_READ_REG 0x00 //¶ÁÅäÖüĴæÆ÷,µÍ5λΪ¼Ä´æÆ÷µØÖ·
#define NRF24L01_WRITE_REG 0x20 //дÅäÖüĴæÆ÷,µÍ5λΪ¼Ä´æÆ÷µØÖ·
#define NRF24L01_RD_RX_PLOAD 0x61 //¶ÁRXÓÐЧÊý¾Ý,1~32×Ö½Ú
#define NRF24L01_WR_TX_PLOAD 0xA0 //дTXÓÐЧÊý¾Ý,1~32×Ö½Ú
#define NRF24L01_FLUSH_TX 0xE1 //Çå³ýTX FIFO¼Ä´æÆ÷.·¢ÉäģʽÏÂÓÃ
#define NRF24L01_FLUSH_RX 0xE2 //Çå³ýRX FIFO¼Ä´æÆ÷.½ÓÊÕģʽÏÂÓÃ
#define NRF24L01_REUSE_TX_PL 0xE3 //ÖØÐÂʹÓÃÉÏÒ»°üÊý¾Ý,CEΪ¸ß,Êý¾Ý°ü±»²»¶Ï·¢ËÍ.
#define NRF24L01_NOP 0xFF //¿Õ²Ù×÷,¿ÉÒÔÓÃÀ´¶Á״̬¼Ä´æÆ÷
//SPI(NRF24L01)¼Ä´æÆ÷µØÖ·
#define CONFIG 0x00 //ÅäÖüĴæÆ÷µØÖ·;bit0:1½ÓÊÕģʽ,0·¢Éäģʽ;bit1:µçÑ¡Ôñ;bit2:CRCģʽ;bit3:CRCʹÄÜ;
//bit4:ÖжÏMAX_RT(´ïµ½×î´óÖØ·¢´ÎÊýÖжÏ)ʹÄÜ;bit5:ÖжÏTX_DSʹÄÜ;bit6:ÖжÏRX_DRʹÄÜ
#define EN_AA 0x01 //ʹÄÜ×Ô¶¯Ó¦´ð¹¦ÄÜ bit0~5,¶ÔӦͨµÀ0~5
#define EN_RXADDR 0x02 //½ÓÊÕµØÖ·ÔÊÐí,bit0~5,¶ÔӦͨµÀ0~5
#define SETUP_AW 0x03 //ÉèÖõØÖ·¿í¶È(ËùÓÐÊý¾ÝͨµÀ):bit1,0:00,3×Ö½Ú;01,4×Ö½Ú;02,5×Ö½Ú;
#define SETUP_RETR 0x04 //½¨Á¢×Ô¶¯ÖØ·¢;bit3:0,×Ô¶¯ÖØ·¢¼ÆÊýÆ÷;bit7:4,×Ô¶¯ÖØ·¢ÑÓʱ 250*x+86us
#define RF_CH 0x05 //RFͨµÀ,bit6:0,¹¤×÷ͨµÀƵÂÊ;
#define RF_SETUP 0x06 //RF¼Ä´æÆ÷;bit3:´«ÊäËÙÂÊ(0:1Mbps,1:2Mbps);bit2:1,·¢É书ÂÊ;bit0:µÍÔëÉù·Å´óÆ÷ÔöÒæ
#define STATUS 0x07 //״̬¼Ä´æÆ÷;bit0:TX FIFOÂú±êÖ¾;bit3:1,½ÓÊÕÊý¾ÝͨµÀºÅ(×î´ó:6);bit4,´ïµ½×î¶à´ÎÖØ·¢
//bit5:Êý¾Ý·¢ËÍÍê³ÉÖжÏ;bit6:½ÓÊÕÊý¾ÝÖжÏ;
#define MAX_TX 0x10 //´ïµ½×î´ó·¢ËÍ´ÎÊýÖжÏ
#define TX_OK 0x20 //TX·¢ËÍÍê³ÉÖжÏ
#define RX_OK 0x40 //½ÓÊÕµ½Êý¾ÝÖжÏ
#define OBSERVE_TX 0x08 //·¢Ëͼì²â¼Ä´æÆ÷,bit7:4,Êý¾Ý°ü¶ªÊ§¼ÆÊýÆ÷;bit3:0,ÖØ·¢¼ÆÊýÆ÷
#define CD 0x09 //Ôز¨¼ì²â¼Ä´æÆ÷,bit0,Ôز¨¼ì²â;
#define RX_ADDR_P0 0x0A //Êý¾ÝͨµÀ0½ÓÊÕµØÖ·,×î´ó³¤¶È5¸ö×Ö½Ú,µÍ×Ö½ÚÔÚÇ°
#define RX_ADDR_P1 0x0B //Êý¾ÝͨµÀ1½ÓÊÕµØÖ·,×î´ó³¤¶È5¸ö×Ö½Ú,µÍ×Ö½ÚÔÚÇ°
#define RX_ADDR_P2 0x0C //Êý¾ÝͨµÀ2½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P3 0x0D //Êý¾ÝͨµÀ3½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P4 0x0E //Êý¾ÝͨµÀ4½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P5 0x0F //Êý¾ÝͨµÀ5½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define TX_ADDR 0x10 //·¢Ë͵ØÖ·(µÍ×Ö½ÚÔÚÇ°),ShockBurstTMģʽÏÂ,RX_ADDR_P0Óë´ËµØÖ·ÏàµÈ
#define RX_PW_P0 0x11 //½ÓÊÕÊý¾ÝͨµÀ0ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P1 0x12 //½ÓÊÕÊý¾ÝͨµÀ1ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P2 0x13 //½ÓÊÕÊý¾ÝͨµÀ2ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P3 0x14 //½ÓÊÕÊý¾ÝͨµÀ3ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P4 0x15 //½ÓÊÕÊý¾ÝͨµÀ4ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P5 0x16 //½ÓÊÕÊý¾ÝͨµÀ5ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define FIFO_STATUS 0x17 //FIFO״̬¼Ä´æÆ÷;bit0,RX FIFO¼Ä´æÆ÷¿Õ±êÖ¾;bit1,RX FIFOÂú±êÖ¾;bit2,3,±£Áô
//bit4,TX FIFO¿Õ±êÖ¾;bit5,TX FIFOÂú±êÖ¾;bit6,1,Ñ»··¢ËÍÉÏÒ»Êý¾Ý°ü.0,²»Ñ»·;
//
//24L01²Ù×÷Ïß
#define NRF24L01_IRQ (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5))
#define Set_NRF24L01_CE {GPIO_SetBits(GPIOA,GPIO_Pin_4);}
#define Clr_NRF24L01_CE {GPIO_ResetBits(GPIOA,GPIO_Pin_4);}
#define Set_NRF24L01_CSN {GPIO_SetBits(GPIOC,GPIO_Pin_4);}
#define Clr_NRF24L01_CSN {GPIO_ResetBits(GPIOC,GPIO_Pin_4);}
//24L01·¢ËͽÓÊÕÊý¾Ý¿í¶È¶¨Òå
#define TX_ADR_WIDTH 5 //5×ֽڵĵØÖ·¿í¶È
#define RX_ADR_WIDTH 5 //5×ֽڵĵØÖ·¿í¶È
#define TX_PLOAD_WIDTH 32 //20×Ö½ÚµÄÓû§Êý¾Ý¿í¶È
#define RX_PLOAD_WIDTH 32 //20×Ö½ÚµÄÓû§Êý¾Ý¿í¶È
void NRF24L01_SPI_Init(void);
void NRF24L01_Init(void);//³õʼ»¯
void RX_Mode(void);//ÅäÖÃΪ½ÓÊÕģʽ
void TX_Mode(void);//ÅäÖÃΪ·¢ËÍģʽ
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//дÊý¾ÝÇø
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//¶ÁÊý¾ÝÇø
u8 NRF24L01_Read_Reg(u8 reg); //¶Á¼Ä´æÆ÷
u8 NRF24L01_Write_Reg(u8 reg, u8 value);//д¼Ä´æÆ÷
u8 NRF24L01_Check(void);//¼ì²é24L01ÊÇ·ñ´æÔÚ
u8 NRF24L01_TxPacket(u8 *txbuf);//·¢ËÍÒ»¸ö°üµÄÊý¾Ý
u8 NRF24L01_RxPacket(u8 *rxbuf);//½ÓÊÕÒ»¸ö°üµÄÊý¾Ý