nrf24l01一主一从代码学习stc8g

该代码示例展示了如何使用NRF24L01无线收发模块进行一对一的通信,主要应用于51单片机学习机。程序中包含了初始化配置、按键控制发送和接收LED状态以及错误处理等功能。通过按键K1、K2、K3可改变LED颜色并发送相应指令,接收端则根据接收到的指令改变LED状态。
摘要由CSDN通过智能技术生成

谢谢b站的学电超人的代码。
备份学习

主程序main.c

/*
标题:NRF24L01收发一体程序 用于一对一收发
主频:35MHz
用于:51单片机学习机-学电
版权:学电科技 
官网:https://xuedian.tech
*/

#include "stc8g.h"
#include "delay.h"
#include "nrf24l01.h"


/* 发光二极管引脚定义 */
sbit LED_R = P0^5;    // 红色LED
sbit LED_Y = P0^6;    // 黄色LED
sbit LED_G = P0^7;    // 绿色LED

/* 按键引脚定义 */ 
sbit K1 = P3^7;     // 按键K1
sbit K2 = P3^6;     // 按键K2
sbit K3 = P3^5;     // 按键K3

unsigned char rece_buf[32];


/* 把IO口初始化为双向模式 */
void IO_Init(void)
{
	P0M0 = 0x00;   //设置P0.0~P0.7为双向口模式
	P0M1 = 0x00;
	P1M0 = 0x00;   //设置P1.0~P1.7为双向口模式
	P1M1 = 0x00;
	P2M0 = 0x00;   //设置P2.0~P2.7为双向口模式
	P2M1 = 0x00;
	P3M0 = 0x00;   //设置P3.0~P3.7为双向口模式
	P3M1 = 0x00;
	P4M0 = 0x00;   //设置P4.0~P4.7为双向口模式
	P4M1 = 0x00;
	P5M0 = 0x00;   //设置P5.0~P5.7为双向口模式
	P5M1 = 0x00;
}

/**********************************************/
void main(void)
{
	unsigned int cnt=0;
	
	IO_Init();
	delay_ms(100); // 延时待系统稳定
	
	while(NRF24L01_Check()); // 等待检测到NRF24L01,程序才会向下执行
	NRF24L01_Init(); // NRF24L01初始化配置 初始化为接收模式
	
	/* 3个LED依次亮一下 */
	LED_R = 0;
	delay_ms(100);
	LED_R = 1;
	LED_Y = 0;
	delay_ms(100);
	LED_Y = 1;
	LED_G = 0;
	delay_ms(100);
	LED_G = 1;
	
	while (1)
	{
		if(K1==0) // 如果按键K1按下
		{
			delay_ms(25);
			if(K1==0)  // 再次确认按键K1是否按下
			{
				LED_R = !LED_R; // 改变红色LED的显示状态
				TX_Mode(); // 配置为无线发送模式
				rece_buf[0]=0x01; // 给要发送的32个字节的第1个字节写1
				NRF24L01_TxPacket(rece_buf);        // 无线发送数据
				RX_Mode(); // 配置为无线接收模式
			}
			while(K1==0); // 如果按键K1按着 就一直在这里执行
		}
		if(K2==0)  // 如果按键K2按下
		{
			delay_ms(25);
			if(K2==0) 
			{
				LED_Y = !LED_Y;
				TX_Mode(); // 配置为无线发送模式
				rece_buf[0]=0x02; // 给要发送的32个字节的第1个字节写2
				NRF24L01_TxPacket(rece_buf);        // 无线发送数据
				RX_Mode(); // 配置为无线接收模式
			}
			while(K2==0);
		}
		if(K3==0)  // 如果按键K3按下
		{
			delay_ms(25);
			if(K3==0)
			{
				LED_G = !LED_G;
				TX_Mode(); // 配置为无线发送模式
				rece_buf[0]=0x03; // 给要发送的32个字节的第1个字节写3
				NRF24L01_TxPacket(rece_buf);        // 无线发送数据
				RX_Mode(); // 配置为无线接收模式
			}
			while(K3==0);
		}
		if(NRF_IRQ==0)	 // 如果无线模块接收到数据
		{
			if(NRF24L01_RxPacket(rece_buf)==0)  // 如果正确接收到数据
			{
			  if((rece_buf[0])==0x01)  // 如果收到的32个字节中的第1个字节是1
				{
					LED_R = !LED_R;
				}
				else if((rece_buf[0])==0x02)  // 如果收到的32个字节中的第1个字节是2
				{
					LED_Y = !LED_Y;
				}
				else if((rece_buf[0])==0x03)  // 如果收到的32个字节中的第1个字节是3
				{
					LED_G = !LED_G;
				}
			}
		}
	}
}









NRF24L01.c

#include "nrf24l01.h"

/* 定义发送和接收地址 */
const unsigned char TX_ADDRESS[TX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28}; 
const unsigned char RX_ADDRESS[RX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28}; 

/* SPI通信收发一个字节 */
unsigned char SPI_RW(unsigned char dat)
{
	unsigned char i;
	
	for(i=0; i<8; i++) // 输出8位
	{
		NRF_MOSI=(dat&0x80); // MSB TO MOSI
		dat=(dat<<1);	// shift next bit to MSB
		NRF_SCK=1;
		dat|=NRF_MISO;	        // capture current MISO bit
		NRF_SCK=0;
	}
	return dat;
}

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

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

	return status;
}

/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节)      */
/* 入口参数:reg  要读的寄存器地址               */
/* 出口参数:value 读出寄存器的值                */
/*************************************************/
unsigned char NRF24L01_Read_Reg(unsigned char reg)
{
 	unsigned char 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 状态值                   */
/*********************************************/
unsigned char NRF24L01_Read_Buf(unsigned char reg,unsigned char *pBuf,unsigned char len)
{
	unsigned char status,i;
	NRF_CSN=0;                   //CSN=0       
  	status=SPI_RW(reg);//发送寄存器地址,并读取状态值   	   
 	for(i=0; i<len; i++)
	pBuf[i]=SPI_RW(0XFF);//读出数据
	NRF_CSN=1;                 //CSN=1
  	return status;        //返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节)  */
/* 入口参数:reg  要写的寄存器地址            */
/*           *pBuf 值的存放数组               */
/*           len   数组字节长度               */
/**********************************************/
unsigned char NRF24L01_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char len)
{
	unsigned char status, i;
	
	NRF_CSN=0;
  status = SPI_RW(reg);//发送寄存器值(位置),并读取状态值
  for(i=0; i<len; i++)
		SPI_RW(*pBuf++); //写入数据
	NRF_CSN=1;
	
  return status;          //返回读到的状态值
}							  					   

/*********************************************/
/* 函数功能:24L01接收数据                   */
/* 入口参数:rxbuf 接收数据数组              */
/* 返回值: 0   成功收到数据                 */
/*          1   没有收到数据                 */
/*********************************************/
unsigned char NRF24L01_RxPacket(unsigned char *rxbuf)
{
	unsigned char state;
	 
	state=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值    	 
	NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
	if(state&RX_OK)//接收到数据
	{
		NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
		NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
		return 0; 
	}	   
	return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
unsigned char NRF24L01_TxPacket(unsigned char *txbuf)
{
	unsigned char 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  不存在                      */
/********************************************/ 
unsigned char NRF24L01_Check(void)
{
	unsigned char check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
	unsigned char check_out_buf[5]={0x00};

	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;
}	

/* NRF24L01初始化配置 初始化为接收模式 */
void NRF24L01_Init(void)
{	
	NRF_CE=0;		  
  NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
	NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(unsigned char*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 
	NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(unsigned char*)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,40);       //设置RF通道为125
	NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27);  //7db增益,250kbps 
	NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器    
	NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器    
	NRF_CE=1;	//CE置高
}

/* 配置为发送模式 */
void TX_Mode(void)  
{
	NRF_CE=0;
	NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断
	NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
	NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除RX FIFO寄存器 
	NRF_CE=1;		  
}

/* 配置为接收模式 */
void RX_Mode(void)  
{
	NRF_CE=0;		  
	NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
	NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
	NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除RX FIFO寄存器 
	NRF_CE=1;		  
}



nrf24L01.h

#ifndef __NRF24L01_H
#define __NRF24L01_H

#include "stc8g.h"

/**********  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字节有效数据宽度

sbit NRF_CSN  = P4^7;
sbit NRF_IRQ  = P1^6;
sbit NRF_CE   = P1^5;
sbit NRF_SCK  = P1^4;
sbit NRF_MISO = P1^3;
sbit NRF_MOSI = P1^2;

unsigned char NRF24L01_Check(void);
void NRF24L01_Init(void);
unsigned char NRF24L01_RxPacket(unsigned char *rxbuf);
unsigned char NRF24L01_TxPacket(unsigned char *txbuf);
void TX_Mode(void);
void RX_Mode(void);












#endif




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值