51单片机控制NRF24L01发送和接受数据

#include<reg51.h>
#include<intrins.h>
#include "lcd1602.h"

//
typedef unsigned char U8; /* defined for unsigned 8-bits integer variable 无符号8位整型变量 */
typedef signed char S8; /* defined for signed 8-bits integer variable 有符号8位整型变量 */
typedef unsigned int U16; /* defined for unsigned 16-bits integer variable 无符号16位整型变量 */
typedef signed int S16; /* defined for signed 16-bits integer variable 有符号16位整型变量 */
typedef unsigned long U32; /* defined for unsigned 32-bits integer variable 无符号32位整型变量 */
typedef signed long S32; /* defined for signed 32-bits integer variable 有符号32位整型变量 */
typedef float F32; /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */
typedef double F64; /* double precision floating point variable (64bits) 双精度浮点数(64位长度) */
//

#define uchar unsigned char
#define uint  unsigned int

const uchar TX_ADDRESS[TX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址
const uchar RX_ADDRESS[RX_ADR_WIDTH]={0xFF,0xFF,0xFF,0xFF,0xFF}; //发送地址

sbit NRF_CE   = P1^5;
sbit NRF_SCK  = P1^4;
sbit NRF_MISO = P1^3;
sbit NRF_CSN  = P1^2;
sbit NRF_MOSI = P1^1;
sbit NRF_IRQ  = P1^0;
sbit BEEP=P3^6;
sbit key=P3^2;
sbit LED2=P1^7;
uchar Rx_buf[32];

/*******函数的声明************/
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);	//指定位置显示一个字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData); //指定位置显示一串字符
void RH_Init(U8 *humi,U8 *temp);
void Init_Timer0(void);
void Delay400Ms(); //
void LCMInit(); //LCM初始化
void Delay5Ms(); 
/*******变量的定义************/

U8 code rh[] ={" RH:  "};
U8 code tmp[] ={" temp:  "};
U8 code nrf1[] ={" NRF2401 OK!"};
U8 code nrf2[] ={" NRF2401 Error!"};

/***************************************************************/
/*********************2401所需延时函数***************************/
/*******************************************************************/
void delay_us(uchar num)
{
	uchar i; 
	for(i=0;i>num;i++)
 	_nop_();
}
void delay_150us()
{
	uint i;

	for(i=0;i>150;i++);
}
void delay(uint t)
{
	uchar k;
	while(t--)
	for(k=0;k<200;k++);
}
/***************************************************************/
/*写地址,读数据
/*******************************************************************/
uchar SPI_RW(uchar byte)
{
	uchar bit_ctr;
	for(bit_ctr=0;bit_ctr<8;bit_ctr++)  // 输出8位
	{
		NRF_MOSI=(byte&0x80); 			// MSB TO MOSI
		byte=(byte<<1);					// shift next bit to MSB
		NRF_SCK=1;
		byte|=NRF_MISO;	        		// capture current MISO bit
		NRF_SCK=0;
	}
	return byte;
}

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

	NRF_CSN=0;                  //CSN=0;   
  	status = SPI_RW(reg);		//发送寄存器地址,并读取状态值
	SPI_RW(value);
	NRF_CSN=1;                  //CSN=1;

	return status;
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节)      */
/* 入口参数:reg  要读的寄存器地址               */
/* 出口参数:value 读出寄存器的值                */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
 	uchar value;

	NRF_CSN=0;              //CSN=0;   
  	SPI_RW(reg);			//发送寄存器值(位置),并读取状态值
	value = SPI_RW(NOP);
	NRF_CSN=1;             	//CSN=1;

	return value;
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节)   */
/* 入口参数:reg   寄存器地址                */
/*           *pBuf 读出寄存器值的存放数组    */
/*           len   数组字节长度              */
/* 出口参数:status 状态值                   */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
	uchar status,u8_ctr;
	NRF_CSN=0;                   	//CSN=0       
  	status=SPI_RW(reg);				//发送寄存器地址,并读取状态值   	   
 	for(u8_ctr=0;u8_ctr<len;u8_ctr++)
	pBuf[u8_ctr]=SPI_RW(0XFF);		//读出数据
	NRF_CSN=1;                 		//CSN=1
  	return status;        			//返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节)  */
/* 入口参数:reg  要写的寄存器地址            */
/*           *pBuf 值的存放数组               */
/*           len   数组字节长度               */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
	uchar 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   没有收到数据                 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
	uchar state;
	 
	state=NRF24L01_Read_Reg(STATUS);  			//读取状态寄存器的值    	 
	NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
	if(state&RX_OK)								//接收到数据
	{
		NRF_CE = 0;
		NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
		NRF24L01_Write_Reg(FLUSH_RX,0xff);					//清除RX FIFO寄存器
		NRF_CE = 1;
		delay_150us(); 
		return 0; 
	}	   
	return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
	uchar state;
   
	NRF_CE=0;												//CE拉低,使能24L01配置
  	NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);	//写数据到TX BUF  32个字节
 	NRF_CE=1;												//CE置高,使能发送	   
	while(NRF_IRQ==1);										//等待发送完成
	state=NRF24L01_Read_Reg(STATUS);  						//读取状态寄存器的值	   
	NRF24L01_Write_Reg(WRITE_REG+STATUS,state); 			//清除TX_DS或MAX_RT中断标志
	if(state&MAX_TX)										//达到最大重发次数
	{
		NRF24L01_Write_Reg(FLUSH_TX,0xff);					//清除TX FIFO寄存器 
		return MAX_TX; 
	}
	if(state&TX_OK)											//发送完成
	{
		return TX_OK;
	}
	return 0xff;											//发送失败
}

/********************************************/
/* 函数功能:检测24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/ 	  
uchar NRF24L01_Check(void)
{
	uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
	uchar check_out_buf[5]={0x00};

	NRF_SCK=0;
	NRF_CSN=1;    
	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;
	else return 1;
}			

/*********************************************/
/*******函数功能:24L01初始化              ***/
/*********************************************/
void NRF24L01_RT_Init(void)
{	
	NRF_CE=0;		  
  	NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
	NRF24L01_Write_Reg(FLUSH_RX,0xff);									//清除RX FIFO寄存器    
  	NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
  	NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  
  	NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答    
  	NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
  	NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
  	NRF24L01_Write_Reg(WRITE_REG+RF_CH,0);        //设置RF通道为2.400GHz  频率=2.4+0GHz
  	NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0F);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  	NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	NRF_CE=1;									  //CE置高,使能发送
}
/*********************************************/
/*******函数功能:发送数据                 ***/
/*********************************************/
void SEND_BUF(uchar *buf)
{
	NRF_CE=0;
	NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);
	NRF_CE=1;
	delay_us(15);
	NRF24L01_TxPacket(buf);
	NRF_CE=0;
	NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);
	NRF_CE=1;	
}

/*********************************************/
/******************main函数*************** ***/
/*********************************************/
void main(void)
{
    
	U8 temperature;
	U8 humidity;
	Init_Timer0();

	Delay400Ms(); //启动等待,等LCM讲入工作状态
	LCMInit(); //LCM初始化
	Delay5Ms(); //延时片刻 
	while(NRF24L01_Check())	// 等待检测到NRF24L01,程序才会向下执行
	{
	 DisplayListChar(2, 0, nrf2);
	 Delay400Ms(); 
	}
    NRF24L01_RT_Init();	
    Delay5Ms();
	Delay5Ms();
	Delay5Ms(); 
	Delay5Ms();
	LCMInit(); //LCM初始化
	DisplayListChar(2, 0, nrf1);
	Delay400Ms();
	Delay400Ms();
	Delay400Ms();
	Delay400Ms();
	Delay400Ms();
	LED2=1;
	Delay400Ms();//延时片刻
	LCMInit(); //LCM初始化
	LED2=0;
	DisplayListChar(0, 0, rh);
	DisplayListChar(0, 1, tmp);
	DisplayOneChar(6, 0, '%');
	DisplayOneChar(8, 1, 'C');
	while(1)
	{
	if(NRF_IRQ==0)	 	// 如果无线模块接收到数据
		{		
			if(NRF24L01_RxPacket(Rx_buf)==0)
			{
			 //LCMInit(); //LCM初始化
          	 Delay5Ms(); //延时片刻 			   
			 DisplayOneChar(4, 0,Rx_buf[1]+0x30);
			 DisplayOneChar(5, 0,Rx_buf[2]+0x30);
			 DisplayOneChar(6, 1,Rx_buf[3]+0x30);
			 DisplayOneChar(7, 1,Rx_buf[4]+0x30);		
			}
		}
	 // LED2=0;
      Delay400Ms();
	}
}
/*********************************************************
 500us延时函数
 晶振:11.0592MHz
*********************************************************/
void delay500(void)
{
  uchar  i;
  for(i=230;i>0;i--);
}
//超温、超湿进入中断
 /*
********************************************************************************
** 函数名称 : Init_Timer0(void)
** 函数功能 : 定时器初始化子程序
********************************************************************************
*/
void Init_Timer0(void)		  //定时器初始化子程序
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
    TH0=(65536-46080)/256; //装初值11.0592M晶振定时50ms数为46080
    TL0=(65536-46080)%256;
	EA=1;            //总中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}

/*
********************************************************************************
** 函数名称 : Timer0_isr(void) interrupt 1 using 1
** 函数功能 : 定时器中断程序
********************************************************************************
*/
void Timer0_isr(void) interrupt 1 using 1
{
	TH0=(65536-46080)/256; //装初值11.0592M晶振定时50ms数为46080
    TL0=(65536-46080)%256;
	
	if(Rx_buf[1]>7||Rx_buf[3]>2)
	{
   	 BEEP=0;
	 delay500();
	 BEEP=1;
	 delay500();
	}
	else BEEP=1;

}
51单片机nrf24l01是常用的物联网无线通信模块,可以实现无线控制、无线通信等多种功能。本文将详细介绍使用51单片机控制nrf24l01的步骤和程序。 首先,我们需要建立相应的电路连接。将nrf24l01模块的VCC引脚接到51单片机的3.3V输出引脚上,将GND引脚接到51单片机的地线上。将nrf24l01模块的CE引脚连接到51单片机的P1口,将CSN引脚连接到51单片机的P2口,将MOSI、MISO和SCK三根引脚分别连接到51单片机的P3.1、P3.2和P3.0上。最后,将IRQ引脚连接到51单片机的P3.3上。 接下来,我们需要编写程序。首先,需要初始化nrf24l01模块和51单片机的SPI接口。然后,设置nrf24l01模块的工作模式、通信频道和数据速率。接着,设置nrf24l01模块的地址和通信地址,以确保数据可以正确地收发。最后,使用循环结构读取或写入数据。 在收发数据时,需要使用不同的模式。在发送数据时,我们需要调用nrf24l01模块的发送数据函数,并向函数传递要发送数据。在接收数据时,我们需要设置nrf24l01模块的接收数据模式,并调用接收数据函数。 在设计nrf24l01收发数据程序时,还需要考虑数据的协议,以及如何解析和处理数据。常用的数据传输协议包括SPI、I2C、UART等,我们需要根据实际需求选择合适的协议。另外,需要注意数据长度、数据类型、校验位等参数的设置,以确保数据的正确性和完整性。 总之,使用51单片机控制nrf24l01模块收发数据需要设计合适的电路连接和程序,需要深入理解nrf24l01模块的工作原理和数据传输协议,以确保数据的可靠性和实时性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值