爲了方便大家測試程序,先將程序開發環境說明一下,程序是在 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<<RX_DR) | (1<<TX_DS) | (1<<MAX_RT) )
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; i<len; i++)
{
pBuf[i] = SPI_Read_Write_Byte(0xFF); // 讀數據
}
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<len; i++)
{
SPI_Read_Write_Byte(*pBuf++);
}
NRF24L01_SET_CS_HIGH();
}
/**
* @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; i<Width; i++ )
{
pRxBuf[i] = SPI_Read_Write_Byte( 0xFF ); // 讀數據
}
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<length; btmp++ )
{
SPI_Read_Write_Byte( *pTxBuf++ ); // 發送數據
}
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<<MASK_RX_DR ) |*/ // 接收中斷
( 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; i<nLen; i++)
{
ddh = 48 + 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<len; i++)
{
SendData_1(*dat++);
}
}
// 定時器 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 <STC/STC15.H>
#include <INTRINS.H>
#include <STRING.H>
#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;
項目截圖
項目配置
STC15-ISP 配置
編譯結果
有很大警告,這些警告是因爲有些函數聲明,定義了,但是沒有調用造成的,總體來說不影響使用.
測試,數據發送接收正常.
總結一下:
使用 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