为了方便大家测试程序,先将程序开发环境说明一下,程序是在 STC15W4K56S4 上开发的,开发板,nRF24L01 无线模块都是某宝淘来的.
原理图 PDF: https://download.csdn.net/download/longzhishen/10407195
好,项目新建好了,现在开始添加文件
分别添加新建以下几个文件
1.main.c // 主文件
2.nRF24L01.h/nRF24L01.c // nRF24L01 驱动
3.Sys.h/Sys.c // 包含单片机内部资源的一些文件(定时器/UART/SPI…等驱动)
4.Constant.h/Variable.c // 常量和变量
首先是 main.c
#include "Constant.h"
#include "nRF24L01.h"
#include "sys.h"
char str[16]="Hello World 0\r\n";
void nRF24L01_Process()
{
#if(NRF24L01_RF_MODE == NRF24L01_TX_MODE)
unsigned char n;
if(Sys_Flag_A.nRF24L01_Send_Data_Flag) // 这是一个标志, 放在 UpdateClock() 中, 每 1 秒会更新一次
{
Sys_Flag_A.nRF24L01_Send_Data_Flag = 0;
SendString_1("RF24L01 Send Data \r\n");
n = nRF24L01_Tx_Packet(str, 16);
if(n == TX_OK) // 发射是否成功
SendString_1("RF24L01 Send OK \r\n"); // 成功
else if(n == MAX_TX)
SendString_1("RF24L01 Send MAX_TX \r\n"); // 超时
else
SendString_1("RF24L01 Send Fail \r\n"); // 发射失败
str[12]++;
if(str[12] > '9')
str[12] = '0';
RED_LED = 1;
}
#else
RED_LED = ~RED_LED;
nRF24L01_Buf_Size = nRF24L01_Rx_Packet(RxPayload);
// 是否接收到数据
if(nRF24L01_Buf_Size)
{
Send_Data_Buf_1(RxPayload, nRF24L01_Buf_Size); // 发送接收到的数据到 串口 1
nRF24L01_Buf_Size = 0;
}
#endif
}
void Sys_Init(void)
{
/*
P0M1 P0M0
0 ------ 0 准双向口
0 ------ 1 推挽输出(强上拉输出,可达 20mA,要加限流电阻)
1 ------ 0 高阻输入(电流既不能流入,也不能流出)
1 ------ 1 开漏,内部上拉电阻断开,开漏模式即可读外部状态,也可对外输出(高电平、低电平),需外部加上拉电阻
*/
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
CLK_DIV &= 0xF8; // 主时钟频率/1 不分频
_nop_();
_nop_();
/*
0x00 主时钟频率/1 不分频
0x01 主时钟频率/2
0x02 主时钟频率/4
0x03 主时钟频率/8
0x04 主时钟频率/16
0x05 主时钟频率/32
0x06 主时钟频率/64
0x07 主时钟频率/128
如果改变 系统时钟 则串口波特率会变
*/
CLK_DIV |= 0x00; // 主时钟频率/1
_nop_();
_nop_();
_nop_();
_nop_();
Clock_Init();
SPI_Init();
Uart_1_Init();
nRF24L01_Init();
Time0_Init();
}
void main()
{
Sys_Init();
while(1)
{
UpdateClock(); // 时钟更新
nRF24L01_Process(); // nRF24L01 数据收发处理
}
}
nRF24L01.h 文件
#ifndef _NRF24L01_H_
#define _NRF24L01_H_
#include "Constant.h"
#include "sys.h"
// nRF24L01 工作模式, 发射模式/接收模式
#define NRF24L01_TX_MODE (0) // 接收模式/主机
#define NRF24L01_RX_MODE (1) // 接收模式/从机
#define NRF24L01_RF_MODE NRF24L01_TX_MODE
/** 从机通道设置 */
#define RX_CHANGE_0 (0x01)
#define RX_CHANGE_1 (0x02)
#define RX_CHANGE_2 (0x04)
#define RX_CHANGE_3 (0x08)
#define RX_CHANGE_4 (0x10)
#define RX_CHANGE_5 (0x20)
#define RF_RX_CHANGE (RX_CHANGE_2) // 从机通道选择
#define DYNAMIC_PACKET 1 // 1:动态包, 0: 固定
#define FIXED_PACKET_LEN 32 // 包长度
#define REPEAT_CNT 15 // 重复次数
#if(NRF24L01_RF_MODE == NRF24L01_TX_MODE)
#define RF_TX_CHANGE (0x3F) // 发射模式要打通所以 接收通道
#define RF_CHANGE (RF_TX_CHANGE)
#else
#define RF_CHANGE (RX_CHANGE_0) // 接收模式通道
#endif
/** RF24L01 硬件接口定义 */
#define NRF24L01_CE SPI_CE
#define NRF24L01_IRQ SPI_IRQ
#define NRF24L01_CS SPI_NSS
/** I/O 口操作函数 */
#define NRF24L01_SET_CE_HIGH() NRF24L01_CE = 1
#define NRF24L01_SET_CE_LOW() NRF24L01_CE = 0
#define NRF24L01_SET_CS_HIGH() SPI_SET_NSS_HIGH()
#define NRF24L01_SET_CS_LOW() SPI_SET_NSS_LOW()
#define RF24L01_GET_IRQ_STATUS() (( 1 != NRF24L01_IRQ ) ? 0 : 1 )
typedef enum ModeType
{
MODE_TX = 0,
MODE_RX
}nRf24l01ModeType;
typedef enum SpeedType
{
SPEED_250K = 0,
SPEED_1M,
SPEED_2M
}nRf24l01SpeedType;
typedef enum PowerType
{
POWER_F18DBM = 0,
POWER_F12DBM,
POWER_F6DBM,
POWER_0DBM
}nRf24l01PowerType;
//NRF24L01 寄存器操作命令
#define NRF_READ_REG 0x00 // 读配置寄存器, 低 5 位为寄存器地址
#define NRF_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 R_RX_PL_WID 0x60
#define NOP 0xFF // 空操作, 可以用来读取状态寄存器
#define W_ACK_PLOAD 0xA8
#define WR_TX_PLOAD_NACK 0xB0
// SPI ( nRF24L01 ) 寄存器地址
/*
配置寄存器地址, Bit0: 1 接收模式
0 发射模式
Bit1: 电选择
Bit2: CRC 模式
Bit3: CRC 使能
Bit4: 中断 MAX_RT (达到最大重发次数中断) 使能
Bit5: 中断 TX_DS 使能
Bit6: 中断 RX_DR 使能
*/
#define CONFIG 0x00
#define EN_AA 0x01 // 使能自动应答功能 Bit0 - 5, 对应通道 0 - 5
#define EN_RXADDR 0x02 // 接收地址允许, Bit0 - 5, 对应通道 0 - 5
#define SETUP_AW 0x03 // 设置地址宽度 ( 所有数据通道 ) : Bit0-1: 00 3字节 01 4字节 10 5字节
#define SETUP_RETR 0x04 // 建立自动重发, Bit0-3: 自动重发计数, Bit4-7: 自动重发延时 250 * x + 86us
#define RF_CH 0x05 // RF 通道, Bit0-6: 工作通道频率
#define RF_SETUP 0x06 // RF 寄存器, Bit3: 传输速度 (0: 1 Mbps, 1: 2 Mbps), Bit1-2: 发射功率, Bit0: 低噪声发大器增益
#define STATUS 0x07 // 状态寄存器, Bit0: RX FIFO 满标志, Bit1-3: 接收数据通道号 (最大: 6 ), Bit4: 达到最多次重发, Bit5: 数据发送完成中断, Bit6: 接收数据中断
#define MAX_TX 0x10 // 达到最大发送次数中断
#define TX_OK 0x20 // TX 发送完成中断
#define RX_OK 0x40 // 接收到数据中断
#define OBSERVE_TX 0x08 // 发送检测寄存器, Bit4-7: 数据包丢失计数器, Bit0-3: 重发计数器
#define CD 0x09 // 载波检测寄存器, Bit0: 载波检测
#define RX_ADDR_P0 0x0A // 数据通道 0 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P1 0x0B // 数据通道 1 接收地址, 最大长度 5 个字节, 低字节在前
#define RX_ADDR_P2 0x0C // 数据通道 2 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P3 0x0D // 数据通道 3 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P4 0x0E // 数据通道 4 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define RX_ADDR_P5 0x0F // 数据通道 5 接收地址, 最低字节可设置, 高字节必须同 RX_ADDR_P1[39:8]相等
#define TX_ADDR 0x10 // 发送地址 (低字节在前), ShockBurstTM 模式下, RX_ADDR_P0 与地址相等
#define RX_PW_P0 0x11 // 接收数据通道 0 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P1 0x12 // 接收数据通道 1 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P2 0x13 // 接收数据通道 2 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P3 0x14 // 接收数据通道 3 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P4 0x15 // 接收数据通道 4 有效数据宽度 (1-32字节), 设置为 0 则非法
#define RX_PW_P5 0x16 // 接收数据通道 5 有效数据宽度 (1-32字节), 设置为 0 则非法
#define FIFO_STATUS 0x17 // FIFO 状态寄存器, Bit0: RX FIFO 寄存器空标志, Bit1 RX FIFO 满标志, Bit2-3 保留
// Bit4 TX FIFO 空标志, Bit5 TX FIFO 满标志, Bit6 1 循环发送上一次数据包, 0 不循环
#define DYNPD 0x1C // 启用动态数据长度, Bit6-7: NULL, Bit5: 启用动态数据长度管道 5
#define FEATRUE 0x1D // 功能寄存器, Bit3-7: 无用,总是为 0, Bit2: 启用动态数据长度, Bit1: 启用 ACK, Bit0: 启用 W_TX_PAYLOAD_NOACK 命令
//???
#define MASK_RX_DR 6
#define MASK_TX_DS 5
#define MASK_MAX_RT 4
#define EN_CRC 3
#define CRCO 2
#define PWR_UP 1
#define PRIM_RX 0
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
#define AW_RERSERVED 0x0
#define AW_3BYTES 0x1
#define AW_4BYTES 0x2
#define AW_5BYTES 0x3
#define ARD_250US (0x00<<4)
#define ARD_500US (0x01<<4)
#define ARD_750US (0x02<<4)
#define ARD_1000US (0x03<<4)
#define ARD_2000US (0x07<<4)
#define ARD_4000US (0x0F<<4)
#define ARC_DISABLE 0x00
#define ARC_15 0x0F
#define CONT_WAVE 7
#define RF_DR_LOW 5
#define PLL_LOCK 4
#define RF_DR_HIGH 3
//bit2-bit1:
#define PWR_18DB (0x00<<1)
#define PWR_12DB (0x01<<1)
#define PWR_6DB (0x02<<1)
#define PWR_0DB (0x03<<1)
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
//for bit3-bit1,
#define TX_FULL_0 0
#define RPD 0
#define TX_REUSE 6
#define TX_FULL_1 5
#define TX_EMPTY 4
//bit3-bit2, reserved, only '00'
#define RX_FULL 1
#define RX_EMPTY 0
#define DPL_P5 5
#define DPL_P4 4
#define DPL_P3 3
#define DPL_P2 2
#define DPL_P1 1
#define DPL_P0 0
#define EN_DPL 2
#define EN_ACK_PAY 1
#define EN_DYN_ACK 0
#define IRQ_ALL ( (1<
extern unsigned char nRF24L01_Buf_Size;
extern xdata unsigned char TxPayload[32];
extern xdata unsigned char RxPayload[32];
unsigned char nRF24L01_Read_Reg( unsigned char RegAddr ); // 读取 nRF24L01 寄存器
unsigned char nRF24L01_Read_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len); // 读取 nRF24L01 数据
void nRF24L01_Write_Reg(unsigned char Reg_Addr, unsigned char dat); // 写 nRF24L01 寄存器
void nRF24L01_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len); // 写 nRF24L01 数据
void nRF24L01_Flush_Tx_Fifo ( void ); // 清发送 FIFO 缓存
void nRF24L01_Flush_Rx_Fifo( void ); // 清接收 FIFO 缓存
void nRF24L01_Reuse_Tx_Payload( void );
void nRF24L01_Nop( void );
unsigned char nRF24L01_Read_Status_Register( void ); // 读取状态寄存器
unsigned char nRF24L01_Clear_IRQ_Flag( unsigned char IRQ_Source ); // 清中断标志
unsigned char nRF24L01_Read_IRQ_Status( void );
unsigned char nRF24L01_Read_Top_Fifo_Width( void );
unsigned char nRF24L01_Read_Rx_Payload( unsigned char *pRxBuf );
void nRF24L01_Write_Tx_Payload_Ack( unsigned char *pTxBuf, unsigned char len );
void nRF24L01_Write_Tx_Payload_NoAck( unsigned char *pTxBuf, unsigned char len );
void nRF24L01_Write_Tx_Payload_InAck( unsigned char *pData, unsigned char len );
void nRF24L01_Set_TxAddr( unsigned char *pAddr, unsigned char len );
void nRF24L01_Set_RxAddr( unsigned char PipeNum, unsigned char *pAddr, unsigned char Len );
void nRF24L01_Set_Speed( nRf24l01SpeedType Speed );
void nRF24L01_Set_Power( nRf24l01PowerType Power );
void nRF24LL01_Write_Hopping_Point( unsigned char FreqPoint );
void nRF24L01_Set_Mode( nRf24l01ModeType Mode ); // 设置 nRF24L01 工作模式,发射/接收(主机/从机)
unsigned char nRF24L01_Check( void ); // 检测 nRF24L01 模块
unsigned char nRF24L01_Tx_Packet( unsigned char *txbuf, unsigned char Length ); // 通过 nRF24L01 发送数据包
unsigned char nRF24L01_Rx_Packet( unsigned char *rxbuf ); // 从 nRF24L01 接收数据包
void nRF24L01_Init( void ); // 初始化 nRF24L01 模块
#endif
nRF24L01.c 文件
#include "nRF24L01.h"
unsigned char nRF24L01_Buf_Size;
xdata unsigned char TxPayload[32];
xdata unsigned char RxPayload[32];
unsigned char code INIT_ADDR0[5]={0x02,0x3A,0xB1,0xB1,0x01};
unsigned char code INIT_ADDR1[5]={0x02,0x3A,0x01,0x01,0x01};
unsigned char code INIT_ADDR2[5]={0x03,0x3A,0x01,0x01,0x01};
unsigned char code INIT_ADDR3[5]={0x04,0x3A,0x01,0x01,0x01};
unsigned char code INIT_ADDR4[5]={0x05,0x3A,0x01,0x01,0x01};
unsigned char code INIT_ADDR5[5]={0x06,0x3A,0x01,0x01,0x01};
/**
* @brief :NRF24L01 读寄存器
* @param :
@Addr: 寄存器地址
* @note : 地址在设备中有效
* @retval: 读数据
*/
unsigned char nRF24L01_Read_Reg(unsigned char Reg_Addr)
{
unsigned reg_val;
NRF24L01_SET_CS_LOW(); // 片选
SPI_Read_Write_Byte(Reg_Addr); // 读命令地址
reg_val = SPI_Read_Write_Byte(0xFF); // 读数据
NRF24L01_SET_CS_HIGH();
return reg_val;
}
/**
* @brief :NRF24L01 读指定长度数据
* @param :
* @reg: 地址
* @pBuf: 数据存放地址
* @len: 数据长度
* @note : 数据长度不超过 255, 地址在设备中有效
* @retval: 读取状态
*/
unsigned char nRF24L01_Read_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len)
{
unsigned char status, i;
NRF24L01_SET_CS_LOW(); // 片选
status = SPI_Read_Write_Byte(Reg_Addr); // 读命令地址
for(i=0; i0xFF); // 读数据
}
NRF24L01_SET_CS_HIGH();
return status;
}
/**
* @brief :NRF24L01 写寄存器
* @param :无
* @note :地址在设备中有效
* @retval:读写状态
*/
void nRF24L01_Write_Reg(unsigned char Reg_Addr, unsigned char dat)
{
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
SPI_Read_Write_Byte(dat);
NRF24L01_SET_CS_HIGH();
}
/**
* @brief :NRF24L01 写指定长度数据
* @param :
* @reg: 地址
* @pBuf: 写入的数据地址
* @len: 数据长度
* @note : 数据长度不超过 255, 地址在设备中有效
* @retval:
*/
void nRF24L01_Write_Buf(unsigned char Reg_Addr, unsigned char *pBuf, unsigned char len)
{
unsigned char i;
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte(NRF_WRITE_REG | Reg_Addr);
for(i=0; i/**
* @brief : 清空 TX 缓冲区
* @param : 无
* @note : 无
* @retval: 无
*/
void nRF24L01_Flush_Tx_Fifo ( void )
{
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( FLUSH_TX ); // 清空 TX FIFO 命令
NRF24L01_SET_CS_HIGH();
}
/**
* @brief : 清空 RX 缓冲区
* @param : 无
* @note : 无
* @retval: 无
*/
void nRF24L01_Flush_Rx_Fifo( void )
{
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( FLUSH_RX ); // 清 RX FIFO 命令
NRF24L01_SET_CS_HIGH();
}
/**
* @brief : 重新使用上一包数据
* @param : 无
* @note : 无
* @retval: 无
*/
void nRF24L01_Reuse_Tx_Payload( void )
{
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( REUSE_TX_PL ); // 重新使用上一包命令
NRF24L01_SET_CS_HIGH();
}
/**
* @brief : NRF24L01 空操作
* @param : 无
* @note : 无
* @retval: 无
*/
void nRF24L01_Nop( void )
{
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte(NOP);
NRF24L01_SET_CS_HIGH();
}
/**
* @brief :NRF24L01 读状态寄存器
* @param :无
* @note :无
* @retval:RF24L01 状态
*/
unsigned char nRF24L01_Read_Status_Register( void )
{
unsigned char Status;
NRF24L01_SET_CS_LOW();
Status = SPI_Read_Write_Byte( NRF_READ_REG + STATUS ); // 读取状态寄存器
NRF24L01_SET_CS_HIGH();
return Status;
}
/**
* @brief : NRF24L01 清中断
* @param :
@IRQ_Source: 中断源
* @note : 无
* @retval: 清除后状态寄存器的值
*/
unsigned char nRF24L01_Clear_IRQ_Flag( unsigned char IRQ_Source )
{
unsigned char btmp = 0;
IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ); // 中断标志处理
btmp = nRF24L01_Read_Status_Register(); // 读状态寄存器
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( NRF_WRITE_REG + STATUS ); // 写状态寄存器命令
SPI_Read_Write_Byte( IRQ_Source | btmp ); // 清相应中断标志
NRF24L01_SET_CS_HIGH();
return ( nRF24L01_Read_Status_Register( )); // 返回状态寄存器状态
}
/**
* @brief : 读 RF24L01 中断状态
* @param : 无
* @note : 无
* @retval: 中断状态
*/
unsigned char nRF24L01_Read_IRQ_Status( void )
{
return ( nRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ))); // 返回中断状态
}
/**
* @brief : 读 FIFO 中数据宽度
* @param : 无
* @note : 无
* @retval: 数据宽度
*/
unsigned char nRF24L01_Read_Top_Fifo_Width( void )
{
unsigned char btmp;
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( R_RX_PL_WID ); // 读 FIFO 中数据宽度命令
btmp = SPI_Read_Write_Byte( 0xFF ); // 读数据
NRF24L01_SET_CS_HIGH();
return btmp;
}
/**
* @brief : 读接收到的数据
* @param : 无
* @note : 无
* @retval:
@pRxBuf: 数据存放地址首地址
*/
unsigned char NRF24L01_Read_Rx_Payload( unsigned char *pRxBuf )
{
unsigned char Width, i;
i = ( nRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07; // 读接收状态
Width = nRF24L01_Read_Top_Fifo_Width( ); // 读接收数据个数
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( RD_RX_PLOAD ); // 读有效数据命令
for( i=0; i0xFF ); // 读数据
}
NRF24L01_SET_CS_HIGH();
nRF24L01_Flush_Rx_Fifo(); // 情空 RX FIFO
return Width;
}
/**
* @brief : 发送数据 ( 带应答 )
* @param :
* @pTxBuf: 发送数据地址
* @len: 长度
* @note : 一次不超过 32 个字节
* @retval: 无
*/
void nRF24L01_Write_Tx_Payload_Ack( unsigned char *pTxBuf, unsigned char len )
{
unsigned char btmp;
unsigned char length = ( len > 32 ) ? 32 : len; // 数据长度超过 32 则只发送 32 个
nRF24L01_Flush_Tx_Fifo(); // 清 TX FIFO
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( WR_TX_PLOAD ); // 发送命令
for( btmp=0; btmp// 发送数据
}
NRF24L01_SET_CS_HIGH();
}
/**
* @brief : 发送数据 ( 不带应答 )
* @param :
* @pTxBuf: 发送数据地址
* @len: 长度
* @note : 一次不超过 32 个字节
* @retval: 无
*/
void NRF24L01_Write_Tx_Payload_NoAck( unsigned char *pTxBuf, unsigned char len )
{
if( len > 32 || len == 0 )
{
return ; // 数据长度大于 32 或者等于 0 则不执行
}
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( WR_TX_PLOAD_NACK ); // 发送命令
while( len-- )
{
SPI_Read_Write_Byte( *pTxBuf++ ); // 发送数据
}
NRF24L01_SET_CS_HIGH();
}
/**
* @brief : 在接收模式下向 TX FIFO 写数据 (带 ACK )
* @param :
* @pData: 数据地址
* @len: 长度
* @note : 一次不超过 32 个字节
* @retval: 无
*/
void NRF24L01_Write_Tx_Payload_InAck( unsigned char *pData, unsigned char len )
{
unsigned char btmp;
len = ( len > 32 ) ? 32 : len; // 数据长度大于 32 个则只写 32 个字节
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( W_ACK_PLOAD ); // 命令
for( btmp = 0; btmp < len; btmp ++ )
{
SPI_Read_Write_Byte( *pData++ ); // 写数据
}
NRF24L01_SET_CS_HIGH();
}
/**
* @brief :设置发送地址
* @param :
* @pAddr: 地址存放地址
* @len: 长度
* @note : 无
* @retval: 无
*/
void nRF24L01_Set_TxAddr( unsigned char *pAddr, unsigned char len )
{
len = ( len > 5 ) ? 5 : len; // 地址不能大于 5 个字节
nRF24L01_Write_Buf( TX_ADDR, pAddr, len ); // 写地址
}
/**
* @brief : 设置接收通道地址
* @param :
* @PipeNum: 通道
* @pAddr: 地址存放的地址
* @Len: 长度
* @note : 通道不大于 5 地址长度不大于 5 个字节
* @retval: 无
*/
void NRF24L01_Set_RxAddr( unsigned char PipeNum, unsigned char *pAddr, unsigned char Len )
{
Len = ( Len > 5 ) ? 5 : Len;
PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum; // 通道不大于 5 地址长度不大于 5 个字节
nRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len ); // 写入地址
}
/**
* @brief : 设置通信速度
* @param :
* @Speed: 速度
* @note : 无
* @retval: 无
*/
void nRF24L01_Set_Speed( nRf24l01SpeedType Speed )
{
unsigned char btmp = 0;
btmp = nRF24L01_Read_Reg( RF_SETUP );
btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
if( Speed == SPEED_250K ) // 250K
{
btmp |= ( 1<<5 );
}
else if( Speed == SPEED_1M ) // 1M
{
btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
}
else if( Speed == SPEED_2M ) // 2M
{
btmp |= ( 1<<3 );
}
nRF24L01_Write_Reg( RF_SETUP, btmp );
}
/**
* @brief : 设置功率
* @param :
* @Power: 功率
* @note : 无
* @retval: 无
*/
void NRF24L01_Set_Power( nRf24l01PowerType Power )
{
unsigned char btmp;
btmp = nRF24L01_Read_Reg( RF_SETUP ) & ~0x07;
switch( Power )
{
case POWER_F18DBM:
btmp |= PWR_18DB;
break;
case POWER_F12DBM:
btmp |= PWR_12DB;
break;
case POWER_F6DBM:
btmp |= PWR_6DB;
break;
case POWER_0DBM:
btmp |= PWR_0DB;
break;
default:
break;
}
nRF24L01_Write_Reg( RF_SETUP, btmp );
}
/**
* @brief : 设置频率
* @param :
* @FreqPoint: 频率参数
* @note : 值不大于 127
* @retval: 无
*/
void RF24LL01_Write_Hopping_Point( unsigned char FreqPoint )
{
nRF24L01_Write_Reg( RF_CH, FreqPoint & 0x7F );
}
/**
* @brief : nRF24L01 检测
* @param : 无
* @note : 无
* @retval: 无
*/
unsigned char nRF24L01_Check( void )
{
unsigned char i;
unsigned char buf[5]={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };
unsigned char read_buf[ 5 ] = { 0 };
nRF24L01_Write_Buf( TX_ADDR, buf, 5 ); // 写入 5 个字节的地址
nRF24L01_Read_Buf( TX_ADDR, read_buf,5 ); // 读出写入的地址
for( i = 0; i < 5; i++ )
{
if( buf[i] != read_buf[i] )
return false; // 读出的值和写入的值不同
}
return true;
}
/**
* @brief : 设置模式
* @param :
* @Mode: 发送模式/接收模式
* @note : 无
* @retval: 无
*/
void nRF24L01_Set_Mode( nRf24l01ModeType Mode )
{
unsigned char controlreg = 0;
controlreg = nRF24L01_Read_Reg( CONFIG );
if( Mode == MODE_TX )
{
controlreg &= ~( 1<< PRIM_RX );
}
else
{
if( Mode == MODE_RX )
{
controlreg |= ( 1<< PRIM_RX );
}
}
nRF24L01_Write_Reg( CONFIG, controlreg );
}
/**
* @brief : nRF24L01 发送一次数据
* @param :
* @txbuf: 待发送数据的首地址
* @Length: 发送数据长度
* @note :
* @retval:
* MAX_TX: 达到最大重发次数
* TX_OK: 发送完成
* 0xFF: 其他原因
*/
unsigned char nRF24L01_Tx_Packet( unsigned char *txbuf, unsigned char Length )
{
unsigned char l_Status = 0;
unsigned int l_MsTimes = 0;
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( FLUSH_TX );
NRF24L01_SET_CS_HIGH();
NRF24L01_SET_CE_LOW();
nRF24L01_Write_Buf( W_ACK_PLOAD, txbuf, Length ); // 写数据到 TX BUF 32 字节 TX_PLOAD_WIDTH
NRF24L01_SET_CE_HIGH(); // 启动发送
while( 0 != RF24L01_GET_IRQ_STATUS())
{
Delay1ms(1);
if( 500 == l_MsTimes++ ) // 500ms 还没有发送成功, 重新初始化设备
{
SendString_1("RF24L01 Reset \r\n");
SPI_Init();
nRF24L01_Init();
nRF24L01_Set_Mode( MODE_TX );
break;
}
}
l_Status = nRF24L01_Read_Reg(STATUS); // 读状态寄存器
nRF24L01_Write_Reg( STATUS, 0xFF ); // 清除 TX_DS 或 MAX_RT 中断标志
if( l_Status & MAX_TX ) // 达到最大重发次数
{
nRF24L01_Write_Reg( FLUSH_TX,0xFF ); // 清除 TX FIFO 寄存器
return MAX_TX;
}
if( l_Status & TX_OK ) // 发送完成
{
return TX_OK;
}
return 0xFF; // 其他原因发送失败
}
/**
* @brief : nRF24L01 接收数据
* @param :
* @rxbuf: 接收数据存放地址
* @note : 无
* @retval:
* 0: 接收完成
* 1: 没有接收到数据
*/
unsigned char nRF24L01_Rx_Packet( unsigned char *rxbuf )
{
unsigned char l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
NRF24L01_SET_CS_LOW();
SPI_Read_Write_Byte( FLUSH_RX );
NRF24L01_SET_CS_HIGH();
while( 0 != RF24L01_GET_IRQ_STATUS( ))
{
Delay1ms(1);
if( 10 == l_100MsTimes++ ) // 10 ms 没有接收到数据, 重新初始化模块
{
// 这个地方看实际情况调整
// SPI_Init();
// nRF24L01_Init();
// nRF24L01_Set_Mode( MODE_RX );
break;
}
}
l_Status = nRF24L01_Read_Reg( STATUS ); // 读状态寄存器
nRF24L01_Write_Reg( STATUS,l_Status ); // 清中断
if( l_Status & RX_OK) // 接收到数据
{
l_RxLength = nRF24L01_Read_Reg( R_RX_PL_WID ); // 读取接收到的数据个数
nRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength ); // 接收到数据
nRF24L01_Write_Reg( FLUSH_RX,0xFF ); // 清除 RX FIFO
return l_RxLength;
}
return 0; // 没有收到数据
}
/**
* @brief : nRF24L01 模块初始化
* @param : 无
* @note : 无
* @retval: 无
*/
void nRF24L01_Init( void )
{
// 检查 nRF24L01 模块是否正常
if(nRF24L01_Check())
{
NRF24L01_SET_CE_HIGH();
nRF24L01_Clear_IRQ_Flag( IRQ_ALL );
#if DYNAMIC_PACKET == 1 // 动态包
nRF24L01_Write_Reg( DYNPD, RF_CHANGE ); // 使能通道 1 动态数据长度
nRF24L01_Write_Reg( FEATRUE, 0x07 ); // 0000 01111
#elif DYNAMIC_PACKET == 0 // 固定包长度
L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN ); // 固定数据长度
#endif
nRF24L01_Write_Reg( CONFIG, /*( 1< // 接收中断
( 1 << EN_CRC ) | // 使能 CRC 1 个字节
( 1 << PWR_UP ) ); // 开启设备
nRF24L01_Write_Reg( EN_AA, RF_CHANGE ); // 通道 x 自动应答
nRF24L01_Write_Reg( EN_RXADDR, RF_CHANGE ); // 使能 通道 x 接收
nRF24L01_Write_Reg( SETUP_AW, AW_5BYTES ); // 地址宽度 5 个字节
nRF24L01_Write_Reg( SETUP_RETR, ARD_4000US |
( REPEAT_CNT & 0x0F ) ); // 重复等待时间 4000 US
nRF24L01_Write_Reg( RF_CH, 1 ); // 初始化频率,----------> 这里是可以修改,发射模块接收模块频率必须一样,不然就收不到数据
nRF24L01_Write_Reg( RF_SETUP, 0x26 ); // 0010 0110 1M kbps 0dBm
/*
这是 接收 地址, 如果你需要 1 对 6 的话,则 6 个地址都需要设置,
如果你是 1 对 1 的话, 只设置对应的一个地址就可以
*/
#if(NRF24L01_RF_MODE == NRF24L01_TX_MODE) // 设置 接收 地址
nRF24L01_Set_TxAddr(&INIT_ADDR0[0], 5 ); // 使用通道 0 ,地址 0 发射
nRF24L01_Set_RxAddr( 0, &INIT_ADDR0[0], 5 ); // 通道 0-1 地址都必须设置, 2-5 地址只能设定低 8 位,高 32 位与 1 地址相同
nRF24L01_Set_RxAddr( 1, &INIT_ADDR1[0], 5 );
nRF24L01_Set_RxAddr( 2, &INIT_ADDR2[0], 5 );
nRF24L01_Set_RxAddr( 3, &INIT_ADDR3[0], 5 );
nRF24L01_Set_RxAddr( 4, &INIT_ADDR4[0], 5 );
nRF24L01_Set_RxAddr( 5, &INIT_ADDR5[0], 5 );
#else
// 如果 你是 1 对 6 的话, 那么这里分别就是 6 个从机的 接收地址, 请单独设置
nRF24L01_Set_RxAddr( 0, &INIT_ADDR0[0], 5 ); // 从机接收地址 0 地址
#if (RF_RX_CHANGE == RX_CHANGE_0)
nRF24L01_Set_TxAddr(&INIT_ADDR0[0], 5 ); // 使用通道 0 ,地址 0 发射
#elif (RF_RX_CHANGE == RX_CHANGE_1)
nRF24L01_Set_TxAddr(&INIT_ADDR1[0], 5 ); // 使用通道 0 ,地址 1 发射
#elif (RF_RX_CHANGE == RX_CHANGE_2)
nRF24L01_Set_TxAddr(&INIT_ADDR2[0], 5 ); // 使用通道 0 ,地址 2 发射
#elif (RF_RX_CHANGE == RX_CHANGE_3)
nRF24L01_Set_TxAddr(&INIT_ADDR3[0], 5 ); // 使用通道 0 ,地址 3 发射
#elif (RF_RX_CHANGE == RX_CHANGE_4)
nRF24L01_Set_TxAddr(&INIT_ADDR4[0], 5 ); // 使用通道 0 ,地址 4 发射
#elif (RF_RX_CHANGE == RX_CHANGE_5)
nRF24L01_Set_TxAddr(&INIT_ADDR5[0], 5 ); // 使用通道 0 ,地址 5 发射
#endif
#endif
#if(NRF24L01_RF_MODE == NRF24L01_TX_MODE)
nRF24L01_Set_Mode( MODE_TX ); // 发送模式
#else
nRF24L01_Set_Mode( MODE_RX ); // 接收模式
#endif
#ifdef DEBUG_UART1_OUT
SendString_1("RF24L01 Check OK \r\n");
#endif
}
else
{
#ifdef DEBUG_UART1_OUT
SendString_1("RF24L01 Check Fail \r\n");
#endif
}
}
Sys.h 文件
#ifndef _SYS_H_
#define _SYS_H_
#include "Constant.h"
// SPI 接口定义,参考原理图
sbit SPI_IRQ = P3^3; // 中断
sbit SPI_CE = P3^4; // 使能
sbit SPI_NSS = P1^2; // 片选
sbit SPI_MOSI = P1^3;
sbit SPI_MISO = P1^4;
sbit SPI_SCK = P1^5;
#define SPI_SET_CLK_HIGH() SPI_SCK = 1
#define SPI_SET_CLK_LOW() SPI_SCK = 0
#define SPI_SET_MOSI_HIGH() SPI_MOSI = 1
#define SPI_SET_MOSI_LOW() SPI_MOSI = 0
#define SPI_GET_MISO() (( 1 != SPI_MISO ) ? 0 : 1 )
#define SPI_SET_NSS_HIGH() SPI_NSS = 1
#define SPI_SET_NSS_LOW() SPI_NSS = 0
void SPI_Init(void); // 初始化 SPI
unsigned char SPI_Read_Write_Byte(unsigned char TxByte); // SPI 读写一个字节
void SPI_Read_Write_String(unsigned char *ReadBuffer, unsigned char *WriteBuffer, unsigned int Length); // SPI 读写数据串
// 串口 1
#define FOSC 12000000L // 时钟频率,我这里是使用单片机内部时钟 12MHz
#define BAUD 115200 // 串口波特率
#define TM (65536-(FOSC/4/BAUD))
void Uart_1_Init(); // 串口 1 初始化
void SendData_1(unsigned char dat); // 通过串口 1 发射 1 个字节
void SendString_1(unsigned char *s); // 通过串口 1 发射 1 个字符串 0x00 结尾
void Send_Data_Buf_1(unsigned char *dat, unsigned char len); // 发射指定长度的数据,包括 0x00
// 定时器 1
struct _stClock
{
struct{
unsigned char t100msFlag :1; // 100 ms 时间到
unsigned char t500msFlag :1;
unsigned char t1secFlag :1;
unsigned char t1minFlag :1;
unsigned char t1HorFlag :1;
unsigned char t1WekFlag :1;
unsigned char t1DayFlag :1;
unsigned char t1MonFlag :1;
unsigned char t1YerFlag :1;
}Flag;
unsigned char t1ms;
unsigned char t100ms;
unsigned char t500ms;
unsigned char tSec;
unsigned char tMin;
unsigned char tHor;
unsigned char tDay;
unsigned char tMon;
unsigned char tYer;
unsigned char tWek;
};
extern struct _stClock stClock;
#define T1MS (65536-FOSC/1000) // 1T模式
void Time0_Init();
void Clock_Init();
void UpdateClock();
unsigned char ReturnWeekDay( unsigned int iYear, unsigned char iMonth, unsigned char iDay );
unsigned char GetMaxDay(unsigned char y, unsigned char m);
unsigned char IsLeapYear(unsigned char y);
// 延时 x 微秒
void Delay1us(unsigned char t_ns);
// 延时 x 毫秒
void Delay1ms(unsigned char t_ms);
// 十六进制转字符串
void HexToStr(char *pbDest, unsigned char *pbSrc, unsigned char nLen);
#endif
Sys.c 文件
#include "sys.h"
struct _stClock stClock;
void Delay1us(unsigned char t_ns) //@12.000MHz
{
while(t_ns--);
}
void Delay1ms(unsigned char t_ms) //@12.000MHz
{
unsigned char i;
i = 169;
while(t_ms--)
{
while(i--)
{
_nop_();
_nop_();
}
};
}
void HexToStr(char *pbDest, unsigned char *pbSrc, unsigned char nLen)
{
char ddl,ddh;
int i;
for (i=0; i48 + pbSrc[i] / 16;
ddl = 48 + pbSrc[i] % 16;
if (ddh > 57) ddh = ddh + 7;
if (ddl > 57) ddl = ddl + 7;
pbDest[i*2] = ddh;
pbDest[i*2+1] = ddl;
}
}
void SPI_Init(void)
{
// 引脚配置 部分51单片机不需要
// SCK MOSI NSS CE 配置为推挽输出
// MISO IRQ 配置为输入
P1M1 &= 0xD3; // 1101 0011
P1M1 |= 0x10; // 0001 0000
P1M0 |= 0x2C; // 0010 1100
P3M1 &= 0xEF; // 1110 1111
P3M1 |= 0x08; // 0000 1000
P1M0 |= 0x10; // 0010 1100
// 时钟置低
SPI_SCK = 0;
// MOSI MISO NSS置高
SPI_MOSI = 1;
SPI_NSS = 1;
SPI_CE = 0; // 使能设备
SPI_SET_NSS_HIGH(); // 取消 SPI 片选
}
/**
* @brief : SPI收发一个字节
* @param :
* @TxByte: 发送的数据字节
* @note : 非堵塞式,一旦等待超时,函数会自动退出
* @retval: 接收到的字节
*/
unsigned char SPI_Read_Write_Byte(unsigned char TxByte)
{
unsigned char i, Data;
SPI_SET_CLK_LOW();
for(i=0; i<8; i++)
{
/** 发送 */
if(TxByte & 0x80)
SPI_SET_MOSI_HIGH(); // 如果即将要发送的位为 1 则置高IO引脚
else
SPI_SET_MOSI_LOW(); // 如果即将要发送的位为 0 则置低IO引脚
TxByte <<= 1; // 数据左移一位,先发送的是最高位
SPI_SET_CLK_HIGH();
_nop_();
/* 接收 */
Data <<= 1; // 接收数据左移一位,先接收到的是最高位
if(SPI_GET_MISO())
Data |= 0x01; // 如果接收时IO引脚为高则认为接收到 1
SPI_SET_CLK_LOW();
_nop_();
}
return Data;
}
/**
* @brief :SPI收发字符串
* @param :
* @ReadBuffer: 接收数据缓冲区地址
* @WriteBuffer:发送字节缓冲区地址
* @Length:字节长度
* @note :非堵塞式,一旦等待超时,函数会自动退出
* @retval:无
*/
void SPI_Read_Write_String(unsigned char *ReadBuffer, unsigned char *WriteBuffer, unsigned int Length)
{
SPI_SET_NSS_LOW();
while(Length--)
{
*ReadBuffer = SPI_Read_Write_Byte(*WriteBuffer);
ReadBuffer++;
WriteBuffer++;
}
SPI_SET_NSS_HIGH();
}
// 串口 1
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0; //清除 RI 位
}
}
void Uart_1_Init()
{
SCON = 0x50; // 8位可变波特率
T2L = TM; // 设置波特率重装值
T2H = TM>>8;
AUXR |= 0x15; // T2为1T模式, 并启动定时器2
ES = 1; // 使能串口中断
EA = 1;
}
void SendData_1(unsigned char dat)
{
ES = 0; // 关闭串口中断
SBUF = dat; // 写数据到UART数据寄存器
while(!TI);
TI = 0;
ES = 1; // 使能串口中断
}
void SendString_1(unsigned char *s)
{
while (*s) // 检测字符串结束标志
{
SendData_1(*s++); // 发送当前字符
}
}
void Send_Data_Buf_1(unsigned char *dat, unsigned char len)
{
unsigned char i;
for(i=0; i// 定时器 0
// Timer0 中断函数
void tm0_isr() interrupt 1 using 1
{
stClock.t1ms++;
if(stClock.t1ms >=100)
{
//BLE_LED =~BLE_LED;
stClock.Flag.t100msFlag = true;
stClock.t1ms = 0;
stClock.t100ms++;
if(stClock.t100ms >= 5)
{
stClock.Flag.t500msFlag = true;
stClock.t100ms = 0;
stClock.t500ms++;
if(stClock.t500ms >= 2)
{
stClock.t500ms = 0;
stClock.Flag.t1secFlag = true;
}
GRR_LED = !GRR_LED; // 将测试口取反
}
}
}
void Time0_Init()
{
AUXR |= 0x80; // 定时器0为1T模式
TMOD = 0x00; // 设置定时器为模式0(16位自动重装载)
TL0 = T1MS; // 初始化计时值
TH0 = T1MS >> 8;
TR0 = 1; // 定时器0开始计时
ET0 = 1; // 使能定时器0中断
EA = 1;
}
void Clock_Init()
{
memset(&stClock, 0, sizeof(struct _stClock));
stClock.tYer = 18; // 2018 年
stClock.tMon = 5; // 5 月
stClock.tDay = 11; // 11 日
stClock.tHor = 18; // 18 点
stClock.tMin = 19; // 19 分
stClock.tSec = 0;
stClock.tWek = ReturnWeekDay(2000 + stClock.tYer, stClock.tMon, stClock.tDay); // 计算星期
}
// 平年/闰年计算函数
unsigned char IsLeapYear(unsigned char y)
{
unsigned int year;
year = 2000 + y;
if((year%4==0 && year%100!=0) || year%400==0)
return true;
else
return false;
}
// 计算指定 年/月 判断这个月是多少天
unsigned char GetMaxDay(unsigned char y, unsigned char m)
{
if(m == 2)
{
if(IsLeapYear(y))
return 29;
else
return 28;
}
else if((m == 4)||(m == 6)||(m == 9)||(m == 11))
return 30;
else
return 31;
}
unsigned char ReturnWeekDay( unsigned int iYear, unsigned char iMonth, unsigned char iDay )
{
int iWeek = 0;
unsigned int y = 0, c = 0, m = 0, d = 0;
if ( iMonth == 1 || iMonth == 2 )
{
c = ( iYear - 1 ) / 100;
y = ( iYear - 1 ) % 100;
m = iMonth + 12;
d = iDay;
}
else
{
c = iYear / 100;
y = iYear % 100;
m = iMonth;
d = iDay;
}
iWeek = y + y / 4 + c / 4 - 2 * c + 26 * ( m + 1 ) / 10 + d - 1; // 蔡勒公式
iWeek = iWeek >= 0 ? ( iWeek % 7 ) : ( iWeek % 7 + 7 ); // iWeek为负时取模
if ( iWeek == 0 ) // 星期日不作为一周的第一天
{
iWeek = 7;
}
return iWeek;
}
void UpdateClock()
{
// 1 秒钟
if(stClock.Flag.t1secFlag)
{
stClock.Flag.t1secFlag = false;
Sys_Flag_A.nRF24L01_Send_Data_Flag = 1;
stClock.tSec++;
}
// 1 分钟
if(stClock.tSec >= 60)
{
stClock.tSec = 0;
stClock.Flag.t1minFlag = true;
stClock.tMin++;
}
// 1 小时
if(stClock.tMin >= 60)
{
stClock.tMin = 0;
stClock.Flag.t1HorFlag = true;
stClock.tHor++;
}
// 1 天
if(stClock.tHor >= 24)
{
stClock.tHor = 0;
stClock.Flag.t1DayFlag = true;
stClock.tDay++;
// 计算当前星期几, 1 - 7
stClock.tWek = ReturnWeekDay(2000 + stClock.tYer, stClock.tMon, stClock.tDay);
}
// 一月, GetMaxDay() 用于计算当月有多少天
if(stClock.tDay > GetMaxDay(stClock.tYer, stClock.tMon))
{
stClock.tMon++;
stClock.Flag.t1MonFlag = true;
}
// 1年
if(stClock.tMon > 12)
{
stClock.tMon = 1;
stClock.tYer++;
stClock.Flag.t1YerFlag = true;
}
}
Constant.h 文件
#ifndef _CONSTAN_H_
#define _CONSTAN_H_
#include
#include
#include
#define TRUE (1)
#define FALSE (0)
#define true (1)
#define false (0)
sbit BLE_LED = P0^5;
sbit GRR_LED = P0^6;
sbit RED_LED = P0^7;
#define DEBUG_UART1_OUT (0)
union _uInt
{
struct
{
unsigned char Int8H;
unsigned char Int8L;
}bt;
unsigned int Int16;
};
struct _Sys_Flag_A
{
unsigned char nRF24L01_Send_Data_Flag :1;
};
extern struct _Sys_Flag_A Sys_Flag_A;
#endif
Variable.c 文件
#include "Constant.h"
struct _Sys_Flag_A Sys_Flag_A;
有很大警告,这些警告是因为有些函数声明,定义了,但是没有调用造成的,总体来说不影响使用.
测试,数据发送接收正常.
总结一下:
使用 nRF24L01 遇到最大/最多的问题是,大家搞不清怎么使用 1 对 6 通信问题,其实搞明白了就很简单了.
1.主机发送地址始终必须是通道 0, 接收地址全部打开.
#if(NRF24L01_RF_MODE == NRF24L01_TX_MODE) // 设置 接收 地址
nRF24L01_Set_TxAddr(&INIT_ADDR0[0], 5 ); // 使用通道 0 ,地址 0 发射
nRF24L01_Set_RxAddr( 0, &INIT_ADDR0[0], 5 ); // 通道 0-1 地址都必须设置, 2-5 地址只能设定低 8 位,高 32 位与 1 地址相同
nRF24L01_Set_RxAddr( 1, &INIT_ADDR1[0], 5 );
nRF24L01_Set_RxAddr( 2, &INIT_ADDR2[0], 5 );
nRF24L01_Set_RxAddr( 3, &INIT_ADDR3[0], 5 );
nRF24L01_Set_RxAddr( 4, &INIT_ADDR4[0], 5 );
nRF24L01_Set_RxAddr( 5, &INIT_ADDR5[0], 5 );
2.从机发射地址为 0 通道 0-6 地址,接收地址必须使用通道 0 地址.
nRF24L01_Set_RxAddr( 0, &INIT_ADDR0[0], 5 ); // 从机接收地址 0 地址
#if (RF_RX_CHANGE == RX_CHANGE_0)
nRF24L01_Set_TxAddr(&INIT_ADDR0[0], 5 ); // 使用通道 0 ,地址 0 发射
#elif (RF_RX_CHANGE == RX_CHANGE_1)
nRF24L01_Set_TxAddr(&INIT_ADDR1[0], 5 ); // 使用通道 0 ,地址 1 发射
#elif (RF_RX_CHANGE == RX_CHANGE_2)
nRF24L01_Set_TxAddr(&INIT_ADDR2[0], 5 ); // 使用通道 0 ,地址 2 发射
#elif (RF_RX_CHANGE == RX_CHANGE_3)
nRF24L01_Set_TxAddr(&INIT_ADDR3[0], 5 ); // 使用通道 0 ,地址 3 发射
#elif (RF_RX_CHANGE == RX_CHANGE_4)
nRF24L01_Set_TxAddr(&INIT_ADDR4[0], 5 ); // 使用通道 0 ,地址 4 发射
#elif (RF_RX_CHANGE == RX_CHANGE_5)
nRF24L01_Set_TxAddr(&INIT_ADDR5[0], 5 ); // 使用通道 0 ,地址 5 发射
流程图,不管主机/从机,发送只能使用通道 0, 地址 0-5 发送,接收可以使用 0-5通道 0-5 地址接收.
Tx(通道 0 ,地址 0 发送发送) –> Rx(通道 0 ,地址 0 接收)
Rx(通道 0 ,地址 0 发送) –> Tx(通道 0 接收)
Rx(通道 0 ,地址 1 发送) –> Tx(通道 1 ,地址 1 接收)
Rx(通道 0 ,地址 2 发送) –> Tx(通道 2 ,地址 2 接收)
Rx(通道 0 ,地址 3 发送) –> Tx(通道 3 ,地址 3 接收)
Rx(通道 0 ,地址 4 发送) –> Tx(通道 4 ,地址 4 接收)
Rx(通道 0 ,地址 5 发送) –> Tx(通道 5 ,地址 5 接收)
因为 发射模块 所以接收通道都打开,所以不管从机使用哪个通道发送,都能接收到数据.
而从机的接收,只需打开 0 通道就可以了.
好了,谢谢!
完整项目地址:https://download.csdn.net/download/longzhishen/10408454