第十八章:nRF24L01无线模块

  • Post author:
  • Post category:其他


2.4G应用

发射端:

/*********************************************************************
						巫妖王V3.0开发板例程
			   朱有鹏物联网大讲堂出品(www.zhulaoshi.org)      
		  技术支持和学习讨论请加朱有鹏单片机学习1群 214959925获取
**********************************************************************
模块名称:nRF24L01
模块功能: 2401无线收发模块	
硬件接线:
注意事项:(1)
版    本:V1.00
作    者:朱有鹏(AstonZhu)
时	  间:2018.10.30											  
**********************************************************************/

/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "2401.h"


/*
**********************************************************************
*                         本地全局变量
**********************************************************************
*/
sbit	CE	    = P1^0;
sbit	CSN		= P1^1;
sbit	SCK	    = P1^2;
sbit 	MOSI	= P1^3;
sbit 	MISO	= P1^4;
sbit	IRQ		= P1^5; 

u8  TX_ADDRESS[TX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};	//本地地址
u8  RX_ADDRESS[RX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};	//接收地址

/*
**********************************************************************
*                         内部函数原型声明
**********************************************************************
*/




/********************底层驱动函数源码******************************/
//----------------------------------------------
//发送一字节[MOSI和MISO数据传递]
//----------------------------------------------
u8 NRF24L01SpiSendByte(u8 dat)
{
  	u8 i;
	for (i=0; i<8; i++) 		//output 8-bit
	{
		//写入1位数据
		MOSI = (dat & 0x80);	//output 'uchar', MSB to MOSI
		dat <<= 1;           	// shift next bit into MSB..
		
		//读取1位数据
		SCK = 1;             	// Set SCK high..
		if (MISO)
		{
		 	dat |= 1;
		}
		else
		{             			// capture current MISO bit
		 	dat &= 0xFE;
		}
		SCK = 0;              	// ..then set SCK low again
	}
	return (dat);             	// return read uchar
}

//----------------------------------------------
//延时n个10us
//----------------------------------------------
void DelayN10us(u16 n)	
{
   for (; n>0; n--)
   {
   	 u8 a,b;

     for (b=1; b>0; b--)
         for (a=2; a>0; a--);
   }
}

//----------------------------------------------
//NRF24L01检测是否存在
//----------------------------------------------
u8 NRF24L01Check(void)
{
	u8 bu[5] = {0XA5, 0XA5, 0XA5, 0XA5, 0XA5};
	u8 bu1[5];
	u8 i;   	 
	SpiWriteBuf(WRITE_REG+TX_ADDR, bu, 5);	  //写入5个字节的地址.	
	SpiReadBuf(TX_ADDR, bu1, 5);              //读出写入的地址  	
	for (i=0; i<5; i++)
		if (bu1[i] != 0XA5)
			break;					   
	if (i != 5)
		return 1;                               //NRF24L01不在位	
	return 0;		                                //NRF24L01在位
}	

//----------------------------------------------
//NRF24L01初始化
//---------------------------------------------- 	 
void InitNRF24L01(void)
{
	u8 buf[5] = {0};
	DelayN10us(10);
	CE = 0;    		// chip enable
	CSN= 0;    		// Spi disable 
	
	SpiReadBuf(TX_ADDR, buf, TX_ADR_WIDTH);//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
}

//----------------------------------------------
//函数:uchar SPI_Read(uchar reg)
//功能:NRF24L01的SPI时序,读取指定寄存器的内容
//---------------------------------------------- 
u8 SpiReadReg(u8 reg)
{
	u8 reg_val;

	CSN = 0;                			// CSN low, initialize SPI communication...
	NRF24L01SpiSendByte(reg);            // Select register to read from..
	reg_val = NRF24L01SpiSendByte(0);    // ..then read registervalue
	CSN = 1;                			// CSN high, terminate SPI communication	
	return (reg_val);        			// return register value
}

//----------------------------------------------
//函数:uchar SPI_Write(uchar reg)
//功能:NRF24L01的SPI时序,写入指定寄存器的内容
//---------------------------------------------- 
u8 SpiWriteReg(u8 reg, u8 value)
{
	u8 status = 0;

	CSN = 0;                   			// CSN low, init SPI transaction
	status = NRF24L01SpiSendByte(reg);	// select register
	NRF24L01SpiSendByte(value);          // ..and write value to it..
	CSN = 1;                   			// CSN high again

	return (status);            			// return nRF24L01 status uchar
}

//---------------------------------------------- 
//函数:uint SpiReadBuf
//功能: 用于读数据
//参数:reg:为寄存器地址
//		pBuf:为待读出数据地址
//		uchars:读出数据的个数
//---------------------------------------------- 
u8 SpiReadBuf(u8 reg, u8 *pBuf, u8 Len)
{
	u16 status, i;

	CSN = 0;                    		// Set CSN low, init SPI tranaction
	status = NRF24L01SpiSendByte(reg);   // Select register to write to and read status uchar
	for (i=0; i<Len; i++)
	{
	 	pBuf[i] = NRF24L01SpiSendByte(0);
	}
	CSN = 1;  
	                        
	return (status);                    	// return nRF24L01 status uchar
}

//----------------------------------------------
//函数:uint SpiWriteBuf
//功能: 用于写数据
//参数:reg:为寄存器地址
//		pBuf:为待写入数据地址
//		uchars:写入数据的个数
//----------------------------------------------
u8 SpiWriteBuf(u8 reg, u8 *pBuf, u8 Len)
{
	u16 status, i;

	CSN = 0;            				//SPI使能       
	status = NRF24L01SpiSendByte(reg);   
	for (i=0; i<Len; i++)
	{
	   NRF24L01SpiSendByte(*pBuf);
		pBuf++;
	}
	CSN = 1;           					//关闭SPI

	return (status);   
}

//----------------------------------------------
//函数:RxMode
//功能:数据接收配置 
//----------------------------------------------
void RxMode(void)
{
    u8 buf[5] = {0};

	CE = 0;
	SpiReadBuf(TX_ADDR, buf, TX_ADR_WIDTH);	//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
	//SPI_WR_Reg(WRITE_REG + CONFIG, 0x03);//SPI_WR_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC	,主接收
	//SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    	// 写本地地址	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); 	// 写接收端地址
	SpiWriteReg(WRITE_REG + EN_AA, 0);		      		//频道0自动	ACK应答允许	
	SpiWriteReg(WRITE_REG + EN_RXADDR,0x01);  			//允许接收地址只有频道0,如果需要多频道可以参考Page21  
	SpiWriteReg(WRITE_REG + SETUP_RETR,0x1a); 			//设置自动重发时间和次数:500us + 86us, 10 retrans...
	SpiWriteReg(WRITE_REG + RF_CH, 40);        			//设置信道工作为2.4GHZ,收发必须一致
	SpiWriteReg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); 	//设置接收数据长度,本次设置为32字节
	SpiWriteReg(WRITE_REG + RF_SETUP, 0x0F);   			//设置发射速率为2MHZ,发射功率为最大值0dB
	SpiWriteReg(WRITE_REG + CONFIG, 0x0F);
	CE = 1; 
	DelayN10us(20); //200us
}

//----------------------------------------------
//函数:NRF24L01RxPacket
//功能:数据读取后放入rx_buf接收缓冲区中
//----------------------------------------------
u8 NRF24L01RxPacket(u8 *rx_buf)
{
    u8 flag = 0;
    u8 status;
 	
	status = SpiReadReg(NRFRegSTATUS);	//读取状态寄存其来判断数据接收状况
	
	if (status & 0x40)					//判断是否接收到数据
	{
	  	 CE = 0; 			//SPI使能
		 SpiReadBuf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH);	// read receive payload from RX_FIFO buffer
		 flag = 1;											//读取数据完成标志
	}
	SpiWriteReg(WRITE_REG+NRFRegSTATUS, status);   			//接收到数据后RX_DR,TX_DS,MAX_RT都置高为1,通过写1来清楚中断标志

	return flag;
}

//----------------------------------------------
//函数:TxMode
//功能:数据接收配置 
//----------------------------------------------
void TxMode(void)
{
    CE = 0;

	SpiWriteBuf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
	SpiWriteReg(WRITE_REG + EN_AA, 0);//0x01);      					//  频道0自动	ACK应答允许	
	SpiWriteReg(WRITE_REG + EN_RXADDR,0);// 0x01);  					//  允许接收地址只有频道0,如果需要多频道可以参考Page21  
	SpiWriteReg(WRITE_REG + SETUP_RETR, 0);//0x1a); 					// 设置自动重发时间和次数:500us + 86us, 10 retrans...
	SpiWriteReg(WRITE_REG + RF_CH, 40);        						//   设置信道工作为2.4GHZ,收发必须一致
	SpiWriteReg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); 				//设置接收数据长度,本次设置为32字节
	SpiWriteReg(WRITE_REG + RF_SETUP, 0x0F);   						//设置发射速率为2MHZ,发射功率为最大值0dB

	SpiWriteReg(WRITE_REG + CONFIG, 0x0E);
    CE = 1;
}

//----------------------------------------------
//函数:NRF24L01TxPacket
//功能:发送tx_buf中数据
//----------------------------------------------
void NRF24L01TxPacket(u8 *tx_buf)
{
	CE = 0;			//StandBy I模式	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
	SpiWriteBuf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); 			 // 装载数据	
	CE = 1;		 //置高CE,激发数据发送
}

#ifndef __NRF24L01_H__
#define __NRF24L01_H__


/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "common.h"


/*
**********************************************************************
*                         本地宏定义
**********************************************************************
*/
#define TX_ADR_WIDTH    5   	// 5 uints TX address width
#define RX_ADR_WIDTH    5   	// 5 uints RX address width
#define TX_PLOAD_WIDTH  32  	// 32 uints TX payload
#define RX_PLOAD_WIDTH  32  	// 32 uints TX payload

///***************************************NRF24L01寄存器指令*******************************************************
#define READ_REG        0x00  	// 读寄存器指令
#define WRITE_REG       0x20 	// 写寄存器指令
#define RD_RX_PLOAD     0x61  	// 读取接收数据指令
#define WR_TX_PLOAD     0xA0  	// 写待发数据指令
#define FLUSH_TX        0xE1 	// 冲洗发送 FIFO指令
#define FLUSH_RX        0xE2  	// 冲洗接收 FIFO指令
#define REUSE_TX_PL     0xE3  	// 定义重复装载数据指令
#define NOP             0xFF  	// 保留
///*************************************SPI(nRF24L01)寄存器地址****************************************************
#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
#define EN_RXADDR       0x02  // 可用信道设置
#define SETUP_AW        0x03  // 收发地址宽度设置
#define SETUP_RETR      0x04  // 自动重发功能设置
#define RF_CH           0x05  // 工作频率设置
#define RF_SETUP        0x06  // 发射速率、功耗功能设置
#define NRFRegSTATUS    0x07  // 状态寄存器
#define OBSERVE_TX      0x08  // 发送监测功能
#define CD              0x09  // 地址检测           
#define RX_ADDR_P0      0x0A  // 频道0接收数据地址
#define RX_ADDR_P1      0x0B  // 频道1接收数据地址
#define RX_ADDR_P2      0x0C  // 频道2接收数据地址
#define RX_ADDR_P3      0x0D  // 频道3接收数据地址
#define RX_ADDR_P4      0x0E  // 频道4接收数据地址
#define RX_ADDR_P5      0x0F  // 频道5接收数据地址
#define TX_ADDR         0x10  // 发送地址寄存器
#define RX_PW_P0        0x11  // 接收频道0接收数据长度
#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栈入栈出状态寄存器设置

/*
**********************************************************************
*                         外部函数原型声明
**********************************************************************
*/
u8 NRF24L01SpiSendByte(u8 dat);
void DelayN10us(u16 n);
u8 NRF24L01Check(void);
void InitNRF24L01(void);
u8 SpiReadReg(u8 reg);
u8 SpiWriteReg(u8 reg, u8 value);
u8 SpiReadBuf(u8 reg, u8 *pBuf, u8 Len);
u8 SpiWriteBuf(u8 reg, u8 *pBuf, u8 Len);
void RxMode(void);
u8 NRF24L01RxPacket(u8 *rx_buf);
void TxMode(void);
void NRF24L01TxPacket(u8 *tx_buf);

#endif   /*__NRF24L01_H__ */
/*********************************************************************
						巫妖王V3.0开发板例程
			   朱有鹏物联网大讲堂出品(www.zhulaoshi.org)      
		  技术支持和学习讨论请加朱有鹏单片机学习1群 214959925获取
**********************************************************************
实验序列:24
实验任务: 		
实现现象:
硬件接线:插入2401模块,注意方向是朝外的。
注意事项:(1) 
		  (2) 
		  (3) 
版    本:V1.00
作    者:朱有鹏(AstonZhu)
时	  间:2018.10.30											  
**********************************************************************/

/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "2401.h"


/*
**********************************************************************
*                         本地宏定义
**********************************************************************
*/


/*
**********************************************************************
*                         本地全局变量
**********************************************************************
*/
sbit KEY1 = P3^1;	 				//发送按键 
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;

sbit LED1 = P2^0;					// 
sbit LED2 = P2^1;	 				//发送数据时显示灯+接收到数据后的功能实现灯
 


void delay_ms(u16 z);


/*********************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void main(void)
{
	u8 Tx_Buf1[] = {1};		// 发送的信息1 
	u8 Rx_Buf[32];  		// 接收到的数据暂存器,最多32字节数据  

	InitNRF24L01();
	LED2 = 1;				//初始灯6熄灭   

	while (NRF24L01Check())		//检查不到24l01则报警 
	{
		LED2 = 0;
		delay_ms(200);
		LED2 = 1;
		delay_ms(200);
	}
	while (1)
	{	
		RxMode();							//接收模式  
		while (!NRF24L01RxPacket(Rx_Buf)) 	//等待接收数据,返回1则接收到数据,在等待接收数据期间,可以随时变成发送模式  
	    {
			if (KEY1 == 0)	 				//按了按键1,则变成发送模式,发送对应数据,发送完后变成接收模式 
			{	
				delay_ms(5);				//消抖动 
				if (KEY1 == 0)
				{
			 		while (!KEY1);
					TxMode();	 					//发送模式 
					Tx_Buf1[0] = 1;					//将1发送过去
			    	NRF24L01TxPacket(Tx_Buf1);		//发送命令数据
					LED1 = 0;
			    	delay_ms(300);
					LED1 = 1;
			    	delay_ms(300);					//发送后LED1闪一下 
					break;							//退出最近的循环,从而变回接收模式,这句关键
				 }	
			 }
			 else if (KEY2 == 0)	 				
			 {	
				delay_ms(5);//消抖动 
				if (KEY2 == 0)
				{
			 		while (!KEY2);
					TxMode();	 					//发送模式 
					Tx_Buf1[0] = 2;					//将2发送过去
			    	NRF24L01TxPacket(Tx_Buf1);		//发送命令数据
					LED1 = 0;
			    	delay_ms(300);
					LED1 = 1;
			    	delay_ms(300);					
					break;							//退出最近的循环,从而变回接收模式,这句关键
				 }	
			  }
			  else if (KEY3 == 0)	 					
			  {	
				delay_ms(5);//消抖动 
				if (KEY3 == 0)
				{
			 		while (!KEY3);
					TxMode();	 					//发送模式 
					Tx_Buf1[0] = 3;					//将3发送过去
			    	NRF24L01TxPacket(Tx_Buf1);		//发送命令数据
					LED1 = 0;
			    	delay_ms(300);
					LED1 = 1;
			    	delay_ms(300);					
					break;							//退出最近的循环,从而变回接收模式,这句关键
				 }	
			  }
			  else if (KEY4 == 0)	 					//按了按键8,则变成发送模式,发送对应数据,发送完后变成接收模式 
			  {	
				delay_ms(5);//消抖动 
				if (KEY4 == 0)
				{
			 		while (!KEY4);
					TxMode();	 					//发送模式 
					Tx_Buf1[0] = 4;					//将4发送过去
			    	NRF24L01TxPacket(Tx_Buf1);		//发送命令数据
					LED1 = 0;
			    	delay_ms(300);
					LED1 = 1;
			    	delay_ms(300);					
					break;							//退出最近的循环,从而变回接收模式,这句关键
				 }	
			  }
		 }
		 if (Rx_Buf[0] == 1)	 	//若接收到对应的数据则实现对应功能 
		 {
		     Rx_Buf[0] = 0;				//清空数据 
		     LED2 = 0;
		 	 delay_ms(300);
		 	 LED2 = 1;
		 	 delay_ms(300);				//接收到数据后LED2闪烁1次  
		 }
	}
}



/*********************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : 延时z毫秒
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void delay_ms(u16 z)			//延时函数 
{
	u16 y;

	while (z--)
		for(y=110; y>0; y--);
}

接收端:

/*********************************************************************
						巫妖王V3.0开发板例程
			   朱有鹏物联网大讲堂出品(www.zhulaoshi.org)      
		  技术支持和学习讨论请加朱有鹏单片机学习1群 214959925获取
**********************************************************************
模块名称:nRF24L01
模块功能: 2401无线收发模块	
硬件接线:
注意事项:(1)
版    本:V1.00
作    者:朱有鹏(AstonZhu)
时	  间:2018.10.30											  
**********************************************************************/

/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "2401.h"


/*
**********************************************************************
*                         本地全局变量
**********************************************************************
*/
sbit	CE	    = P1^0;
sbit	CSN		= P1^1;
sbit	SCK	    = P1^2;
sbit 	MOSI	= P1^3;
sbit 	MISO	= P1^4;
sbit	IRQ		= P1^5; 

u8  TX_ADDRESS[TX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};	//本地地址
u8  RX_ADDRESS[RX_ADR_WIDTH]= {0xE7,0xE7,0xE7,0xE7,0xE7};	//接收地址

/*
**********************************************************************
*                         内部函数原型声明
**********************************************************************
*/




/********************底层驱动函数源码******************************/
//----------------------------------------------
//发送一字节[MOSI和MISO数据传递]
//----------------------------------------------
u8 NRF24L01SpiSendByte(u8 dat)
{
  	u8 i;
	for (i=0; i<8; i++) 		//output 8-bit
	{
		//写入1位数据
		MOSI = (dat & 0x80);	//output 'uchar', MSB to MOSI
		dat <<= 1;           	// shift next bit into MSB..
		
		//读取1位数据
		SCK = 1;             	// Set SCK high..
		if (MISO)
		{
		 	dat |= 1;
		}
		else
		{             			// capture current MISO bit
		 	dat &= 0xFE;
		}
		SCK = 0;              	// ..then set SCK low again
	}
	return (dat);             	// return read uchar
}

//----------------------------------------------
//延时n个10us
//----------------------------------------------
void DelayN10us(u16 n)	
{
   for (; n>0; n--)
   {
   	 u8 a,b;

     for (b=1; b>0; b--)
         for (a=2; a>0; a--);
   }
}

//----------------------------------------------
//NRF24L01检测是否存在
//----------------------------------------------
u8 NRF24L01Check(void)
{
	u8 bu[5] = {0XA5, 0XA5, 0XA5, 0XA5, 0XA5};
	u8 bu1[5];
	u8 i;   	 
	SpiWriteBuf(WRITE_REG+TX_ADDR, bu, 5);	  //写入5个字节的地址.	
	SpiReadBuf(TX_ADDR, bu1, 5);              //读出写入的地址  	
	for (i=0; i<5; i++)
		if (bu1[i] != 0XA5)
			break;					   
	if (i != 5)
		return 1;                               //NRF24L01不在位	
	return 0;		                                //NRF24L01在位
}	

//----------------------------------------------
//NRF24L01初始化
//---------------------------------------------- 	 
void InitNRF24L01(void)
{
	u8 buf[5] = {0};
	DelayN10us(10);
	CE = 0;    		// chip enable
	CSN= 0;    		// Spi disable 
	
	SpiReadBuf(TX_ADDR, buf, TX_ADR_WIDTH);//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
}

//----------------------------------------------
//函数:uchar SPI_Read(uchar reg)
//功能:NRF24L01的SPI时序,读取指定寄存器的内容
//---------------------------------------------- 
u8 SpiReadReg(u8 reg)
{
	u8 reg_val;

	CSN = 0;                			// CSN low, initialize SPI communication...
	NRF24L01SpiSendByte(reg);            // Select register to read from..
	reg_val = NRF24L01SpiSendByte(0);    // ..then read registervalue
	CSN = 1;                			// CSN high, terminate SPI communication	
	return (reg_val);        			// return register value
}

//----------------------------------------------
//函数:uchar SPI_Write(uchar reg)
//功能:NRF24L01的SPI时序,写入指定寄存器的内容
//---------------------------------------------- 
u8 SpiWriteReg(u8 reg, u8 value)
{
	u8 status = 0;

	CSN = 0;                   			// CSN low, init SPI transaction
	status = NRF24L01SpiSendByte(reg);	// select register
	NRF24L01SpiSendByte(value);          // ..and write value to it..
	CSN = 1;                   			// CSN high again

	return (status);            			// return nRF24L01 status uchar
}

//---------------------------------------------- 
//函数:uint SpiReadBuf
//功能: 用于读数据
//参数:reg:为寄存器地址
//		pBuf:为待读出数据地址
//		uchars:读出数据的个数
//---------------------------------------------- 
u8 SpiReadBuf(u8 reg, u8 *pBuf, u8 Len)
{
	u16 status, i;

	CSN = 0;                    		// Set CSN low, init SPI tranaction
	status = NRF24L01SpiSendByte(reg);   // Select register to write to and read status uchar
	for (i=0; i<Len; i++)
	{
	 	pBuf[i] = NRF24L01SpiSendByte(0);
	}
	CSN = 1;  
	                        
	return (status);                    	// return nRF24L01 status uchar
}

//----------------------------------------------
//函数:uint SpiWriteBuf
//功能: 用于写数据
//参数:reg:为寄存器地址
//		pBuf:为待写入数据地址
//		uchars:写入数据的个数
//----------------------------------------------
u8 SpiWriteBuf(u8 reg, u8 *pBuf, u8 Len)
{
	u16 status, i;

	CSN = 0;            				//SPI使能       
	status = NRF24L01SpiSendByte(reg);   
	for (i=0; i<Len; i++)
	{
	   NRF24L01SpiSendByte(*pBuf);
		pBuf++;
	}
	CSN = 1;           					//关闭SPI

	return (status);   
}

//----------------------------------------------
//函数:RxMode
//功能:数据接收配置 
//----------------------------------------------
void RxMode(void)
{
    u8 buf[5] = {0};

	CE = 0;
	SpiReadBuf(TX_ADDR, buf, TX_ADR_WIDTH);	//debug 测试原来的本地地址:复位值是:0xE7 0xE7 0xE7 0xE7 0xE7
	//SPI_WR_Reg(WRITE_REG + CONFIG, 0x03);//SPI_WR_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC	,主接收
	//SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    	// 写本地地址	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); 	// 写接收端地址
	SpiWriteReg(WRITE_REG + EN_AA, 0);		      		//频道0自动	ACK应答允许	
	SpiWriteReg(WRITE_REG + EN_RXADDR,0x01);  			//允许接收地址只有频道0,如果需要多频道可以参考Page21  
	SpiWriteReg(WRITE_REG + SETUP_RETR,0x1a); 			//设置自动重发时间和次数:500us + 86us, 10 retrans...
	SpiWriteReg(WRITE_REG + RF_CH, 40);        			//设置信道工作为2.4GHZ,收发必须一致
	SpiWriteReg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); 	//设置接收数据长度,本次设置为32字节
	SpiWriteReg(WRITE_REG + RF_SETUP, 0x0F);   			//设置发射速率为2MHZ,发射功率为最大值0dB
	SpiWriteReg(WRITE_REG + CONFIG, 0x0F);
	CE = 1; 
	DelayN10us(20); //200us
}

//----------------------------------------------
//函数:NRF24L01RxPacket
//功能:数据读取后放入rx_buf接收缓冲区中
//----------------------------------------------
u8 NRF24L01RxPacket(u8 *rx_buf)
{
    u8 flag = 0;
    u8 status;
 	
	status = SpiReadReg(NRFRegSTATUS);	//读取状态寄存其来判断数据接收状况
	
	if (status & 0x40)					//判断是否接收到数据
	{
	  	 CE = 0; 			//SPI使能
		 SpiReadBuf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH);	// read receive payload from RX_FIFO buffer
		 flag = 1;											//读取数据完成标志
	}
	SpiWriteReg(WRITE_REG+NRFRegSTATUS, status);   			//接收到数据后RX_DR,TX_DS,MAX_RT都置高为1,通过写1来清楚中断标志

	return flag;
}

//----------------------------------------------
//函数:TxMode
//功能:数据接收配置 
//----------------------------------------------
void TxMode(void)
{
    CE = 0;

	SpiWriteBuf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
	SpiWriteReg(WRITE_REG + EN_AA, 0);//0x01);      					//  频道0自动	ACK应答允许	
	SpiWriteReg(WRITE_REG + EN_RXADDR,0);// 0x01);  					//  允许接收地址只有频道0,如果需要多频道可以参考Page21  
	SpiWriteReg(WRITE_REG + SETUP_RETR, 0);//0x1a); 					// 设置自动重发时间和次数:500us + 86us, 10 retrans...
	SpiWriteReg(WRITE_REG + RF_CH, 40);        						//   设置信道工作为2.4GHZ,收发必须一致
	SpiWriteReg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); 				//设置接收数据长度,本次设置为32字节
	SpiWriteReg(WRITE_REG + RF_SETUP, 0x0F);   						//设置发射速率为2MHZ,发射功率为最大值0dB

	SpiWriteReg(WRITE_REG + CONFIG, 0x0E);
    CE = 1;
}

//----------------------------------------------
//函数:NRF24L01TxPacket
//功能:发送tx_buf中数据
//----------------------------------------------
void NRF24L01TxPacket(u8 *tx_buf)
{
	CE = 0;			//StandBy I模式	
	SpiWriteBuf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
	SpiWriteBuf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); 			 // 装载数据	
	CE = 1;		 //置高CE,激发数据发送
}

#ifndef __NRF24L01_H__
#define __NRF24L01_H__


/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "common.h"


/*
**********************************************************************
*                         本地宏定义
**********************************************************************
*/
#define TX_ADR_WIDTH    5   	// 5 uints TX address width
#define RX_ADR_WIDTH    5   	// 5 uints RX address width
#define TX_PLOAD_WIDTH  32  	// 32 uints TX payload
#define RX_PLOAD_WIDTH  32  	// 32 uints TX payload

///***************************************NRF24L01寄存器指令*******************************************************
#define READ_REG        0x00  	// 读寄存器指令
#define WRITE_REG       0x20 	// 写寄存器指令
#define RD_RX_PLOAD     0x61  	// 读取接收数据指令
#define WR_TX_PLOAD     0xA0  	// 写待发数据指令
#define FLUSH_TX        0xE1 	// 冲洗发送 FIFO指令
#define FLUSH_RX        0xE2  	// 冲洗接收 FIFO指令
#define REUSE_TX_PL     0xE3  	// 定义重复装载数据指令
#define NOP             0xFF  	// 保留
///*************************************SPI(nRF24L01)寄存器地址****************************************************
#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
#define EN_RXADDR       0x02  // 可用信道设置
#define SETUP_AW        0x03  // 收发地址宽度设置
#define SETUP_RETR      0x04  // 自动重发功能设置
#define RF_CH           0x05  // 工作频率设置
#define RF_SETUP        0x06  // 发射速率、功耗功能设置
#define NRFRegSTATUS    0x07  // 状态寄存器
#define OBSERVE_TX      0x08  // 发送监测功能
#define CD              0x09  // 地址检测           
#define RX_ADDR_P0      0x0A  // 频道0接收数据地址
#define RX_ADDR_P1      0x0B  // 频道1接收数据地址
#define RX_ADDR_P2      0x0C  // 频道2接收数据地址
#define RX_ADDR_P3      0x0D  // 频道3接收数据地址
#define RX_ADDR_P4      0x0E  // 频道4接收数据地址
#define RX_ADDR_P5      0x0F  // 频道5接收数据地址
#define TX_ADDR         0x10  // 发送地址寄存器
#define RX_PW_P0        0x11  // 接收频道0接收数据长度
#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栈入栈出状态寄存器设置

/*
**********************************************************************
*                         外部函数原型声明
**********************************************************************
*/
u8 NRF24L01SpiSendByte(u8 dat);
void DelayN10us(u16 n);
u8 NRF24L01Check(void);
void InitNRF24L01(void);
u8 SpiReadReg(u8 reg);
u8 SpiWriteReg(u8 reg, u8 value);
u8 SpiReadBuf(u8 reg, u8 *pBuf, u8 Len);
u8 SpiWriteBuf(u8 reg, u8 *pBuf, u8 Len);
void RxMode(void);
u8 NRF24L01RxPacket(u8 *rx_buf);
void TxMode(void);
void NRF24L01TxPacket(u8 *tx_buf);

#endif   /*__NRF24L01_H__ */
/*********************************************************************
						巫妖王V3.0开发板例程
			   朱有鹏物联网大讲堂出品(www.zhulaoshi.org)      
		  技术支持和学习讨论请加朱有鹏单片机学习1群 214959925获取
**********************************************************************
实验序列:24
实验任务: 		
实现现象:
硬件接线:插入2401模块,注意方向是朝外的。
注意事项:(1) 
		  (2) 
		  (3) 
版    本:V1.00
作    者:朱有鹏(AstonZhu)
时	  间:2018.10.30											  
**********************************************************************/

/*
**********************************************************************
*                         头文件包含
**********************************************************************
*/
#include "2401.h"


/*
**********************************************************************
*                         本地宏定义
**********************************************************************
*/


/*
**********************************************************************
*                         本地全局变量
**********************************************************************
*/
sbit KEY4 = P3^3;	 				//发送按键 

sbit LED1 = P2^0;					//小灯闪烁提示报警 
sbit LED2 = P2^1;	 				//发送数据时显示灯
sbit LED3 = P2^2;					//接收到数据后的功能实现灯
sbit LED4 = P2^3;
sbit LED5 = P2^4;
sbit LED6 = P2^5;  


void delay_ms(u16 z);


/*********************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void main(void)
{
	u8 Tx_Buf[] = {1};				//发送的信息1 
	u8 Rx_Buf[32];  				//接收到的数据暂存器,最多32字节数据  
	InitNRF24L01();
	LED2 = 1;						//初始灯2熄灭   

	while (NRF24L01Check())					//检查不到24l01则小灯闪烁提示报警 
	{
		LED1 = 0;
		delay_ms(200);
		LED1 = 1;
		delay_ms(200);
	}
	while (1)
	{	
		RxMode();							//接收模式  
		while (!NRF24L01RxPacket(Rx_Buf)) 	//等待接收数据,返回1则接收到数据,在等待接收数据期间,可以随时变成发送模式  
	    {
			if (KEY4 == 0)	 					//按了按键4,则变成发送模式,发送对应数据,发送完后变成接收模式 
			{	
				delay_ms(5);//消抖动 
				if (KEY4 == 0)
				{
			 		while (!KEY4);
					TxMode();	 //发送模式 
			    	NRF24L01TxPacket(Tx_Buf);		//发送命令数据
					LED2 = 0;
			    	delay_ms(300);
					LED2 = 1;
			    	delay_ms(300);					//发送后LED2闪一下 
					break;							//退出最近的循环,从而变回接收模式,这句关键
				 }	
			 }
		 }

		switch (Rx_Buf[0])
		{//对数据进行分析来控制灯亮
			case 0:
				break;
			case 1:
				Rx_Buf[0] = 0;				//清空数据 
			    LED3 = 0;
				delay_ms(300);
				LED3 = 1;
				delay_ms(300);	
				break;
			case 2:
				Rx_Buf[0] = 0;				//清空数据 
			    LED4 = 0;
				delay_ms(300);
				LED4 = 1;
				delay_ms(300);	
				break;
			case 3:
				Rx_Buf[0] = 0;				//清空数据 
			    LED5 = 0;
				delay_ms(300);
				LED5 = 1;
				delay_ms(300);	
				break;
			default:
				Rx_Buf[0] = 0;				//清空数据 
			    LED6 = 0;
				delay_ms(300);
				LED6 = 1;
				delay_ms(300);	
				break;
		}	 	
	}
}


/*********************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : 延时z毫秒
* 参数列表       : 无
* 函数输出    	 : 无
*********************************************************************/
void delay_ms(u16 z)			//延时函数 
{
	u16 y;
	while (z--)
		for (y=110; y>0; y--);
}



版权声明:本文为qq_33553024原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。