nRF24L01+基于51单片机的驱动(库)实战代码分享

关于代码来源

之前我发过几篇关于nRF24L01+的博文,很多网友看后希望能提供完整的驱动库,本人将以前实际应用于实际项目中的一个nRF24L01+的驱动代码完整的分享给大家,希望能对广大nRF24L01+爱好者提供一些帮助。这些代码是参照芯片官方文档针对项目应用改良后的,在实际项目中实践是正常的,如果您在使用中有异议,请参看官方文档。本人提供的代码只供参考,不对代码运行结果承担任何责任。

这里提供的是基于STC15系列的51单片机nRF24L01+驱动库,对于通信组网逻辑,还是要有很多考虑的,否则也可能达不到您希望的结果,尤其是多机或高速频繁交互的时候。

定义数据类型的头文件Type.h

/*************************************************************************************************************
										-- 定义数据类型-头文件 --
文件名称:Type.h
代码整理:闫春林
整理日期:2017年11月24日
免责声明:该程序仅用于学习与交流
调用说明:引入本文件后,直接使用U8、U16、U32分别定义无符号的8位、16位、32位数据类型即可,S8、S16、S32为有符号的
*************************************************************************************************************/

#ifndef	_Type_H_
#define	_Type_H_


typedef unsigned char U8;
typedef unsigned int U16;
typedef unsigned long U32;

typedef signed char S8;
typedef signed int S16;
typedef signed long S32;

#endif

nRF24L01+驱动源代码文件nRF24L01P.c

/*************************************************************************************************************
单元功能:***STC15系列nRF24L01P无线驱动***
文件名称:NRF24L01P.c
代码整理:闫春林----2018年3月25日
免责声明:该程序仅用于学习与交流,不得用于商业用途,不对因使用本代码而产生的任何后果负任何责任
规范说明:为便于阅读,函数名、全局变量使用大驼峰,局部变量使用小驼峰,常量名使用全大写
调用方法:本机地址为全局变量SelfAddr,频道、功率、速率通过公共函数RF24_RfSetup设置
		  功率配置值适应台产SI24R1芯片的模块及nRF24L01P+PA的亿佰特大功率模块,根据使用模块选择对应的功率参数配置
*************************************************************************************************************/
#include "nRF24L01P.h"


U8 SelfAddr[TX_ADR_WIDTH] = {0x01, 0x01, 0x01, 0x01, 0x01};				//本机硬件地址



/**************************************************************************************************************************/
/*=========================================================私有函数=======================================================*/
/**************************************************************************************************************************/

/*-----------------------------------------------------------------------------
函数名称:SPI_RW
输入参数:byte:待发送的一个字节数据
返回数据:收到的一个字节数据
功能描述:模拟SPI接口通讯收发一体化函数
------------------------------------------------------------------------------*/
U8 SPI_RW(U8 byte){
	U8 i;
	for(i=0; i<8; i++)
	{
		if(byte & 0x80)
			MOSI = 1;
		else
			MOSI = 0;
		byte = (byte << 1);
		SCK = 1;
		byte |= MISO;
		SCK = 0;
	}
	return byte;
}

/*-----------------------------------------------------------------------------
函数名称:nRF24L01P_Write_Reg
输入参数:reg:寄存器映射地址(格式:WRITE_REG|reg);value:待写的寄存器值
功能描述:写状态寄存器的值
------------------------------------------------------------------------------*/
void nRF24L01P_Write_Reg(U8 reg, U8 value){
	CSN = 0;
	SPI_RW(reg);
	SPI_RW(value);
	CSN = 1;
}

/*-----------------------------------------------------------------------------
函数名称:nRF24L01P_Write_Buf
输入参数:reg:寄存器映射地址(格式:WRITE_REG|reg);pBuf:待写数据首地址;bytes:写数据字节数
功能描述:写状态寄存器的值
------------------------------------------------------------------------------*/
void nRF24L01P_Write_Buf(U8 reg, const U8 *pBuf, U8 bytes){
	U8 i;

	CSN = 0;                                  			
	SPI_RW(reg);                          
	for(i=0; i<bytes; i++)     
		SPI_RW(*pBuf++);
	CSN = 1;     
}							  					   

/*-----------------------------------------------------------------------------
函数名称:nRF24L01P_Read_Reg
输入参数:reg:寄存器映射地址(格式:READ_REG|reg)
返回数据:寄存器值
功能描述:读状态寄存器的值(单字节)
------------------------------------------------------------------------------*/
U8 nRF24L01P_Read_Reg(U8 reg){
 	U8 value;

	CSN = 0;    
	SPI_RW(reg);			
	value = SPI_RW(0);
	CSN = 1;              

	return(value);
}

/*-----------------------------------------------------------------------------
函数名称:nRF24L01P_Read_Reg
输入参数:reg:寄存器映射地址(格式:READ_REG|reg);pBuf:接收缓冲区的首地址;bytes:读取字节数
功能描述:读状态寄存器的值(多字节)
------------------------------------------------------------------------------*/
void nRF24L01P_Read_Buf(U8 reg, U8 *pBuf, U8 bytes){
	U8 i;

	CSN = 0;                                        
	SPI_RW(reg);                           
	for(i=0; i<bytes; i++)
		pBuf[i] = SPI_RW(0);                   									//读取数据,低字节在前
	CSN = 1;   
}


/**************************************************************************************************************************/
/*=========================================================公有函数=======================================================*/
/**************************************************************************************************************************/

/*-----------------------------------------------------------------------------
函数名称:RF24_RfSetup
输入参数:ch:射频工作频道
功能描述:nRF24L01P+工作频道设置
------------------------------------------------------------------------------*/
void RF24_SetRfCh(U8 ch){
	CE = 0;
	nRF24L01P_Write_Reg(WR_RF_CH, ch);         									//设置变更射频通道
	CE = 1;
}

/*-----------------------------------------------------------------------------
函数名称:RF24_Init
功能描述:nRF24L01P+初始化
------------------------------------------------------------------------------*/
void RF24_Init(){
	SCK = 0; 																	//SPI时钟线拉低
	CSN = 1;																	//片选脚拉高处于未选状态
	CE 	= 0;																	//拉低使能配置,收发时要拉高
	IRQ = 1;																	//中断引脚抬高处于未触发中断状态

	CE = 0;
	nRF24L01P_Write_Reg(WR_SETUP_AW, 0x03);             		  				//设置地址宽度为5字节
	nRF24L01P_Write_Reg(WR_RF_SETUP, RFSETUP);    								//数据传输率、发射功率配置为公共变量RfSetup的值
	nRF24L01P_Write_Reg(WR_EN_AA, 0x01);               							//使能接收通道0自动应答
	nRF24L01P_Write_Reg(WR_EN_RXADDR, 0x01);   									//使能接收通道0
	nRF24L01P_Write_Reg(WR_RX_PW_P0, TX_PLOAD_WIDTH);  							//接收通道0选择和发送通道相同有效数据宽度,仅接收有效
	nRF24L01P_Write_Reg(WR_SETUP_RETR, RETE_VAL);								//自动重发时间间隔和重发次数,仅发送有效
	CE = 1;
}

/*-----------------------------------------------------------------------------
函数名称:RF24_RX_Mode
功能描述:nRF24L01P+设置为接收模式
------------------------------------------------------------------------------*/
void RF24_RX_Mode()
{
	CE = 0;
	nRF24L01P_Write_Buf(WR_RX_ADDR_P0, SelfAddr, TX_ADR_WIDTH);  				//接收设备接收通道0使用和发送设备相同的发送地址
	nRF24L01P_Write_Reg(WR_CONFIG, 0x0F);              							//CRC使能,16位CRC校验,开机,接收模式
	nRF24L01P_Write_Reg(WR_STATUS, 0xFF);  										//清除所有的中断标志位
	CE = 1;                                            							//拉高CE启动接收设备
}						

/*-----------------------------------------------------------------------------
函数名称:RF24_TX_Mode
输入参数:*toAddr:发送目标地址指针
功能描述:nRF24L01P+设置为发送模式
------------------------------------------------------------------------------*/
void RF24_TX_Mode(U8 *toAddr)
{
	CE = 0;
	nRF24L01P_Write_Buf(WR_TX_ADDR, toAddr, TX_ADR_WIDTH);						//写入发送地址
	nRF24L01P_Write_Reg(WR_CONFIG, 0x0E);      									//CRC使能,16位CRC校验,开机,发送模式,屏蔽自动重发中断
	nRF24L01P_Write_Buf(WR_RX_ADDR_P0, toAddr, TX_ADR_WIDTH);					//为了应答接收设备,接收通道0地址和发送地址相同
	nRF24L01P_Write_Reg(WR_STATUS, 0xFF);  										//清除所有的中断标志位
	//CE = 1;
}

/*-----------------------------------------------------------------------------
函数名称:RF24_RxData
输入参数:*rxbuf:保存接收数据的缓冲区指针
返回数据:是否收到数据,1收到,0未收到
功能描述:nRF24L01P+判断是否收到数据,若收到直接取出,应在主循环中调用
------------------------------------------------------------------------------*/
bit RF24_RxData(U8 *rxbuf)
{
	U8 state;

	if(IRQ == 0)																//有中断触发,判断中断可以提高CPU效率,减少SPI通讯量
	{
		state = nRF24L01P_Read_Reg(STATUS);										//读取状态寄存器的值    	  
		nRF24L01P_Write_Reg(WR_STATUS, state);									//清除RX_DS中断标志
		if(state & RX_DR)														//接收到数据
		{
			nRF24L01P_Read_Buf(RD_RX_PLOAD,rxbuf,TX_PLOAD_WIDTH);				//读取数据
			nRF24L01P_Write_Reg(FLUSH_RX,0xFF);									//清除RX FIFO寄存器
			return ON; 
		}
	}	   
	return OFF;																	//没收到任何数据
}

/*-----------------------------------------------------------------------------
函数名称:RF24_TxData
输入参数:*txbuf:待发送数据的缓冲区指针
返回数据:是否发送成功,1发送成功,0发送失败
功能描述:nRF24L01P+发送数据
------------------------------------------------------------------------------*/
bit RF24_TxData(U8 *txbuf)
{
	U8 state;
	
	while(RPD == 1);
	CE=0;																		//CE拉低,使能24L01配置
	nRF24L01P_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);						//写数据到TX FIFO,32个字节
	CE=1;																		//CE置高,使能发送	   

	while(IRQ == 1);															//等待发送完成
	state=nRF24L01P_Read_Reg(STATUS);  											//读取状态寄存器的值	   
	nRF24L01P_Write_Reg(WR_STATUS, state); 										//清除TX_DS或MAX_RT中断标志
	if(state&TX_DS)																//发送完成
		return ON;
	nRF24L01P_Write_Reg(FLUSH_TX,0xff);											//清除TX FIFO寄存器 
	return OFF;																	//发送失败
}

nRF24L01+驱动的头文件nRF24L01P.h

/*************************************************************************************************************
单元功能:***STC15系列nRF24L01P无线驱动***
文件名称:NRF24L01P.h
代码整理:闫春林----2018年3月25日
免责声明:该程序仅用于学习与交流,不得用于商业用途,不对因使用本代码而产生的任何后果负任何责任
规范说明:为偏于阅读,函数名、全局变量使用大驼峰,局部变量使用小驼峰,常量名使用全大写
调用方法:本机地址为全局变量SelfAddr,频道、功率、速率通过公共函数RF24_RfSetup设置
		  功率配置值适应台产SI24R1芯片的模块及nRF24L01P+PA的亿佰特大功率模块,根据使用模块选择对应的功率参数配置
*************************************************************************************************************/
#ifndef __NRF24L01P__
#define __NRF24L01P__

#include "STC15.H"
#include "Sys.h"
#include "Type.h"
#include "Timer.h"


/***************************************MCU到NRF24L01+的引脚定义(用户操作)******************************************/

#define	MOSI				P13				//主机输出,从机输入引脚(输出)
#define	MISO				P14				//主机输入,从机输出引脚(输入)
#define	SCK					P15				//主机输出,串行时钟引脚(输出)
#define	CSN					P16				//主机输出,从机选择引脚(输出到CSN,低电平有效)
#define	CE					P17				//芯片使能信号引脚(输出,I/O口配置为推挽)
#define	IRQ					P12				//来自NRF24L01的中断信号引脚(输入,低电平有效)

#define	AUTO_RESEND_TIME	500				//自动重发时间间隔,单位uS,必须是250的整数倍,最大4000uS,不启用ACK请忽略此项
#define	AUTO_RESEND_NUM		15				//自动重发次数,最多15次,不启用ACK请忽略此项

#define	RFSETUP		        (RATE_1Mbps | E01ML01SP4_20dBm)	   //RF速率和发射功率


/********************************************NRF24L01+数据常用数据值配置**********************************************/

#define TX_ADR_WIDTH		5				//发送/接收地址宽度
#define TX_PLOAD_WIDTH		32				//数据通道有效数据宽度

/*************************************************** 全局变量声明 ***************************************************/

extern U8 SelfAddr[TX_ADR_WIDTH];			//本机硬件地址


/***************************************************NRF24L01+命令*****************************************************/

#define READ_REG			0x00  			//定义读取寄存器命令
#define WRITE_REG			0x20  			//定义写取寄存器命令
#define RD_RX_PLOAD			0x61  			//定义读有效接收数据寄存器指令
#define WR_TX_PLOAD			0xA0  			//定义写有效发送数据寄存器指令
#define WR_TX_PLOAD_NOACK	0xB0  			//定义写有效发送数据寄存器指令,无ACK应答模式
#define FLUSH_TX			0xE1			//定义清洗发送缓冲区FIFO寄存器指令                                  
#define FLUSH_RX			0xE2			//定义清洗接收缓冲区FIFO寄存器指令
#define REUSE_TX_PL			0xE3			//定义重复装载发送数据寄存器指令
#define NOP					0xFF			//定义无操作,可能会被用来读状态寄存器

#define RETE_VAL			((AUTO_RESEND_TIME/250-1)<<4) + AUTO_RESEND_NUM 	//自动重发配置值


/************************************************NRF24L01+寄存器地址**************************************************/

#define CONFIG				0x00			//配置寄存器
#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 STATUS				0x07			//状态寄存器
#define OBSERVE_TX			0x08			//发送检测寄存器
#define RPD					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状态寄存器
#define FEATURE				0x1D			//特征寄存器,ACK负载长度、使能ACK负载、禁用ACK

#define WR_CONFIG			0x20			//写配置寄存器
#define WR_EN_AA			0x21			//写设置自动应答功能寄存器
#define WR_EN_RXADDR		0x22			//写设置使能接收地址寄存器
#define WR_SETUP_AW			0x23			//写设置地址宽度寄存器
#define WR_SETUP_RETR		0x24			//写设置自动重发寄存器
#define WR_RF_CH			0x25			//写设置无线频道寄存器
#define WR_RF_SETUP			0x26			//写设置无线发射速率、功耗寄存器
#define WR_STATUS			0x27			//写状态寄存器
#define WR_OBSERVE_TX		0x28			//写发送检测寄存器
#define WR_RPD				0x29			//写接收功率检测寄存器
#define WR_RX_ADDR_P0		0x2A			//写通道0接收数据地址寄存器
#define WR_RX_ADDR_P1		0x2B			//写通道1接收数据地址寄存器
#define WR_RX_ADDR_P2		0x2C			//写通道2接收数据地址寄存器
#define WR_RX_ADDR_P3		0x2D			//写通道3接收数据地址寄存器
#define WR_RX_ADDR_P4		0x2E			//写通道4接收数据地址寄存器
#define WR_RX_ADDR_P5		0x2F			//写通道5接收数据地址寄存器
#define WR_TX_ADDR			0x30			//写发送目标地址寄存器
#define WR_RX_PW_P0			0x31			//写通道0接收有效数据宽度寄存器
#define WR_RX_PW_P1			0x32			//写通道1接收有效数据宽度寄存器
#define WR_RX_PW_P2			0x33			//写通道2接收有效数据宽度寄存器
#define WR_RX_PW_P3			0x34			//写通道3接收有效数据宽度寄存器
#define WR_RX_PW_P4			0x35			//写通道4接收有效数据宽度寄存器
#define WR_RX_PW_P5			0x36			//写通道5接收有效数据宽度寄存器
#define WR_FIFO_STATUS		0x37			//写FIFO状态寄存器
#define WR_FEATURE			0x3D			//写特征寄存器,ACK负载长度、使能ACK负载、禁用ACK


/*********************************************NRF24L01+状态寄存器状态值***********************************************/
 
#define RX_DR				0x40			//接收成功
#define TX_DS				0x20			//发送成功
#define MAX_RT				0x10			//达到最大重发次数


/*********************************************发射功率与频率配置值***********************************************/

#define RATE_2Mbps			0x08			//2M速率
#define RATE_1Mbps			0x00			//1M速率
#define RATE_250Kbps		0x20			//250K速率

#define SI24R1_7dBm			0x07			//台产SI24R1芯片7dBm
#define SI24R1_4dBm			0x06			//台产SI24R1芯片4dBm
#define SI24R1_3dBm			0x05			//台产SI24R1芯片3dBm
#define SI24R1_1dBm			0x04			//台产SI24R1芯片1dBm
#define SI24R1_0dBm			0x03			//台产SI24R1芯片0dBm
#define SI24R1_f4dBm		0x02			//台产SI24R1芯片-4dBm
#define SI24R1_f6dBm		0x01			//台产SI24R1芯片-6dBm
#define SI24R1_f12dBm		0x00			//台产SI24R1芯片-12dBm

#define E01ML01SP4_20dBm	0x06			//成都亿佰特模块20dBm
#define E01ML01SP4_14dBm	0x04			//成都亿佰特模块14dBm
#define E01ML01SP4_8dBm		0x02			//成都亿佰特模块8dBm
#define E01ML01SP4_2dBm		0x00			//成都亿佰特模块2dBm


/*************************************************** 函数声明 ***************************************************/
void RF24_SetRfCh(U8 ch);							//nRF24L01P+工作频道设置
void RF24_Init();									//nRF24L01P+初始化
void RF24_RX_Mode();								//nRF24L01P+设置为接收模式
void RF24_TX_Mode(U8 *toAddr);						//nRF24L01P+设置为发送模式
bit RF24_RxData(U8 *rxbuf);							//nRF24L01P+判断是否收到数据,若收到直接取出,应在主循环中调用
bit RF24_TxData(U8 *txbuf);							//nRF24L01P+发送数据

#endif

写在后面

如果在使用中遇到问题,请先看我的另一条博文《nRF24L01+不能接收或接收偶尔异常等问题实战分享》,或直接在下面留言!

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学为所用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值