NRF24L01硬件设计和软件实现(STC15)

NRF24L01硬件设计和软件实现(STC15)

上面是我创建的群聊,欢迎新朋友的加入。

NRF24L01硬件设计和软件实现(STC15)

这个东西做了有很久了,STC+NRF24L01方案,当时弄个黑油还花了100大洋。

这个东西有两部分组成,一个无线板,一个底板。

1.无线部分

NRF24L01硬件设计和软件实现(STC15)

原理图是直接照抄数据手册的

NRF24L01硬件设计和软件实现(STC15)

做出来就是绿色的这种

2.STC15底板

NRF24L01硬件设计和软件实现(STC15)

考虑到方便调试,加了一个CH340下载电路

NRF24L01硬件设计和软件实现(STC15)

3.驱动程序实现

#include "nrf24l01.h"

const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; 
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; 
/**********************/
/* SPI数据收发函数    */
/**********************/
u8 SPI_RW(u8 tr_data)
{
	u16 bit_ctr;
	for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
	{
		NRF_MOSI = (tr_data & 0x80);         // output 'uchar', MSB to MOSI
		tr_data = (tr_data << 1);           // shift next bit into MSB..
		NRF_SCK = 1;                      // Set SCK high..
		tr_data |= NRF_MISO;       		  // capture current MISO bit
		NRF_SCK = 0;            		  // ..then set SCK low again
	}
	return(tr_data);           		  // return read uchar
}

/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg   要写的寄存器地址          */
/*           value 给寄存器写的值            */
/* 出口参数:status 状态值                   */
/*********************************************/
u8 NRF24L01_RW_Reg(u8 reg,u8 value)
{
	u16 status;

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

	return(status);            // return nRF24L01 status uchar
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节)      */
/* 入口参数:reg  要读的寄存器地址               */
/* 出口参数:value 读出寄存器的值                */
/*************************************************/
u8 NRF24L01_Read_Reg(u8 reg)
{
	u8 reg_val;
	
	NRF_CSN = 0;                // CSN low, initialize SPI communication...
	SPI_RW(reg);            // Select register to read from..
	reg_val = SPI_RW(0);    // ..then read registervalue
	NRF_CSN = 1;                // CSN high, terminate SPI communication
	
	return(reg_val);        // return register value
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节)   */
/* 入口参数:reg   寄存器地址                */
/*           *pBuf 读出寄存器值的存放数组    */
/*           len   数组字节长度              */
/* 出口参数:status 状态值                   */
/*********************************************/
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
	u16 status,uchar_ctr;
	
	NRF_CSN = 0;                    		// Set CSN low, init SPI tranaction
	status = SPI_RW(reg);       		// Select register to write to and read status uchar
	
	for(uchar_ctr=0;uchar_ctr<len;uchar_ctr++)
		pBuf[uchar_ctr] = SPI_RW(0);    // 
	
	NRF_CSN = 1;                           

	return(status);                    // return nRF24L01 status uchar
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节)  */
/* 入口参数:reg  要写的寄存器地址            */
/*           *pBuf 值的存放数组               */
/*           len   数组字节长度               */
/**********************************************/
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
	u8 status,u8_ctr;
	NRF_CSN=0;
  	status = SPI_RW(reg);//发送寄存器值(位置),并读取状态值
  	for(u8_ctr=0; u8_ctr<len; u8_ctr++)
	SPI_RW(*pBuf++); //写入数据
	NRF_CSN=1;
  return status;          //返回读到的状态值
}							  					   

/*********************************************/
/* 函数功能:24L01接收数据                   */
/* 入口参数:rxbuf 接收数据数组              */
/* 返回值: 0   成功收到数据                 */
/*          1   没有收到数据                 */
/*********************************************/
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
	u8 state;
	unsigned char revale=0; 
	
	state=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值	   
	if(state&RX_OK)//接收到数据
	{
		NRF_CE = 0; 			//SPI使能
		NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
 //   NRF24L01_RW_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 
		revale = 1;
	}	 
	NRF24L01_RW_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
  
	return revale;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
u8 NRF24L01_TxPacket(u8 *txbuf)
{
	u8 state;

	NRF_CE=0;			//StandBy I模式	
	NRF24L01_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
	NRF24L01_Write_Buf(WR_TX_PLOAD, txbuf, TX_PLOAD_WIDTH); 			 // 装载数据	
	NRF24L01_RW_Reg(WRITE_REG + CONFIG, 0x0e);   		 // IRQ收发完成中断响应,16位CRC,主发送
	NRF_CE=1;		 //置高CE,激发数据发送
	while(NRF_IRQ==1);//等待发送完成
	state=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值	   
	NRF24L01_RW_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
	if(state&MAX_TX)//达到最大重发次数
	{
		NRF24L01_RW_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 
		return MAX_TX; 
	}
	if(state&TX_OK)//发送完成
	{
		return TX_OK;
	}
	return 0xff;//发送失败
}
/********************************************/
/* 函数功能:检测24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/ 
u8 NRF24L01_Check(void)
{
	u8 check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
	u8 check_out_buf[20]={0x00};

	NRF_CE=0;

	NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
	NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
	
	if((check_out_buf[0] == 0x11)&&\
	   (check_out_buf[1] == 0x22)&&\
	   (check_out_buf[2] == 0x33)&&\
	   (check_out_buf[3] == 0x44)&&\
	   (check_out_buf[4] == 0x55))return 0;

		return 1;
}	


void NRF24L01_RT_Init(void)
{	 
	NRF_CE=0;    // chip enable
	NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
	NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS ,TX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  
	NRF24L01_RW_Reg(WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答    
	NRF24L01_RW_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
	NRF24L01_RW_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
	NRF24L01_RW_Reg(WRITE_REG+RF_CH,0);       //设置RF通道为125
	NRF24L01_RW_Reg(WRITE_REG+RF_SETUP,0x07);  //7db增益,250kbps 
	NRF24L01_RW_Reg(WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	NRF_CE=1;	//CE置高
}
#ifndef NRF24L01_H_
#define NRF24L01_H_

#include "usart.h"
#include "system.h"

sbit NRF_CE = P1^1;
sbit NRF_CSN = P1^0;
sbit NRF_MISO = P3^3;
sbit NRF_MOSI = P3^6;
sbit NRF_SCK = P3^7;
sbit NRF_IRQ = P3^2;

/**********  NRF24L01寄存器操作命令  ***********/
#define READ_REG        0x00  //读配置寄存器,低5位为寄存器地址
#define WRITE_REG       0x20  //写配置寄存器,低5位为寄存器地址
#define RD_RX_PLOAD     0x61  //读RX有效数据,1~32字节
#define WR_TX_PLOAD     0xA0  //写TX有效数据,1~32字节
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.发射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包数据,CE为高,数据包被不断发送.
#define NOP             0xFF  //空操作,可以用来读状态寄存器	 
/**********  NRF24L01寄存器地址   *************/
#define CONFIG          0x00  //配置寄存器地址                             
#define EN_AA           0x01  //使能自动应答功能 
#define EN_RXADDR       0x02  //接收地址允许
#define SETUP_AW        0x03  //设置地址宽度(所有数据通道)
#define SETUP_RETR      0x04  //建立自动重发
#define RF_CH           0x05  //RF通道
#define RF_SETUP        0x06  //RF寄存器
#define STATUS          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有效数据宽度(1~32字节) 
#define RX_PW_P1        0x12  // 接收数据通道1有效数据宽度(1~32字节) 
#define RX_PW_P2        0x13  // 接收数据通道2有效数据宽度(1~32字节) 
#define RX_PW_P3        0x14  // 接收数据通道3有效数据宽度(1~32字节) 
#define RX_PW_P4        0x15  // 接收数据通道4有效数据宽度(1~32字节)
#define RX_PW_P5        0x16  // 接收数据通道5有效数据宽度(1~32字节)
#define FIFO_STATUS     0x17  // FIFO状态寄存器
/*————————————————————————————————————————————————————————————————————*/
		
/******   STATUS寄存器bit位定义      *******/
#define MAX_TX  	0x10  //达到最大发送次数中断
#define TX_OK   	0x20  //TX发送完成中断
#define RX_OK   	0x40  //接收到数据中断
/*——————————————————————————————————————————————————*/

/*********     24L01发送接收数据宽度定义	  ***********/
#define TX_ADR_WIDTH    5   //5字节地址宽度
#define RX_ADR_WIDTH    5   //5字节地址宽度
#define TX_PLOAD_WIDTH  32  //32字节有效数据宽度
#define RX_PLOAD_WIDTH  32  //32字节有效数据宽度

u8 NRF24L01_Check(void);
void NRF24L01_RT_Init(void);
u8 NRF24L01_TxPacket(u8 *txbuf);
u8 NRF24L01_RxPacket(u8 *rxbuf);
u8 NRF24L01_RW_Reg(u8 reg,u8 value);

#endif