1. nRF24L01無線模塊的工作原理
發射數據時,首先將nRF24L01配置為發射模式:接著把接收節點地址TX_ADDR和有效數據TX_PLD按照時序由SPI口寫入nRF24L01緩存區,TX_PLD必須在CSN為低時連續寫入,而TX_ADDR在發射時寫入一次即可,然後CE置為高電平並保持至少10μs,延遲130μs後發射數據;若自動應答開啟,那麼nRF24L01在發射數據後立即進入接收模式,接收應答信號(自動應答接收地址應該與接收節點地址TX_ADDR一致)。如果收到應答,則認為此次通信成功,TX_DS置高,同時TX_PLD從TX FIFO中清除;若未收到應答,則自動重新發射該數據(自動重發已開啟),若重發次數(ARC)達到上限,MAX_RT置高,TX FIFO中數據保留以便再次重發;MAX_RT或TX_DS置高時,使IRQ變低,產生中斷,通知MCU。最後發射成功時,若CE為低則nRF24L01進入空閑模式1;若發送堆棧中有數據且CE為高,則進入下一次發射;若發送堆棧中無數據且CE為高,則進入空閑模式2。
接收數據時,首先將nRF24L01配置為接收模式,接著延遲130μs進入接收狀態等待數據的到來。當接收方檢測到有效的地址和CRC時,就將數據包存儲在RX FIFO中,同時中斷標志位RX_DR置高,IRQ變低,產生中斷,通知MCU去取數據。若此時自動應答開啟,接收方則同時進入發射狀態回傳應答信號。最後接收成功時,若CE變低,則nRF24L01進入空閑模式1。
2. 求基於51單片機無線模塊nrf24l01程序
剛好正在研究,網上找的,稍改了一下,2015.8.17晚試驗
接收方應該沒問題,但發送方上電一次只能發2 個數據,想再發,單片機復位也不行
必須重新給NRF24L01上電有的網友則只能發一次
單片機用STC12C5A32S2,但硬體SPI不成功,用的是普通IO模擬SPI
#include <reg52.h>
//#include "STC12C5A.H"
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
//****************************************IO埠定義***************************************
sbit CE=P0^0;
sbit CSN=P0^1;
sbit SCK=P0^2;
sbit MOSI=P0^3; //管腳配置
sbit MISO=P0^4;
sbit IRQ=P0^5;
sbit diola=P2^5;//發光二極體鎖存端
sbit anla=P2^6;//段鎖存端 tx-1c開發板
sbit weila=P2^7;//位鎖存端
//************************************按鍵***************************************************
sbit KEY1=P3^4;
uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//*********************************************NRF24L01*************************************
#define TX_ADR_WIDTH 5 // 5 uints TX address width
#define RX_ADR_WIDTH 5 // 5 uints RX address width
#define TX_PLOAD_WIDTH 20 // 20 uints TX payload
#define RX_PLOAD_WIDTH 20 // 20 uints TX payload
uchar TX_ADDRESS[TX_ADR_WIDTH]= {0x12,0x34,0x56,0x78,0x90}; //本地地址
uchar RX_ADDRESS[RX_ADR_WIDTH]= {0x12,0x34,0x56,0x78,0x90}; //接收地址
//***************************************NRF24L01寄存器指令
#define READ_REG 0x00 // 讀寄存器指令
#define WRITE_REG 0x20 // 寫寄存器指令
#define RD_RX_PLOAD 0x61 // 讀取接收數據指令
#define WR_TX_PLOAD 0xA0 // 寫待發數據指令
#define FLUSH_TX 0xE1 // 沖洗發送 FIFO指令
#define FLUSH_RX 0xE2 // 沖洗接收 FIFO指令
#define REUSE_TX_PL 0xE3 // 定義重復裝載數據指令
#define NOP 0xFF // 保留
//*************************************SPI(nRF24L01)寄存器地址
#define CONFIG 0x00 // 配置收發狀態,CRC校驗模式以及收發狀態響應方式
#define EN_AA 0x01 // 自動應答功能設置
#define EN_RXADDR 0x02 // 可用信道設置
#define SETUP_AW 0x03 // 收發地址寬度設置
#define SETUP_RETR 0x04 // 自動重發功能設置
#define RF_CH 0x05 // 工作頻率設置
#define RF_SETUP 0x06 // 發射速率、功耗功能設置
#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接收數據長度
#define RX_PW_P1 0x12 // 接收頻道0接收數據長度
#define RX_PW_P2 0x13 // 接收頻道0接收數據長度
#define RX_PW_P3 0x14 // 接收頻道0接收數據長度
#define RX_PW_P4 0x15 // 接收頻道0接收數據長度
#define RX_PW_P5 0x16 // 接收頻道0接收數據長度
#define FIFO_STATUS 0x17 // FIFO棧入棧出狀態寄存器設置
uchar sta; //狀態標志
#define RX_DR (sta & 0x40)
#define TX_DS (sta & 0x20)
#define MAX_RT (sta & 0x10)
//*****************************************長延時*****************************************
void Delay(unsigned int s)
{
unsigned int i;
for(i=0; i<s; i++);
for(i=0; i<s; i++);
for(i=0; i<s; i++);
for(i=0; i<s; i++);
}
//******************************************************************************************
//***********毫秒延時程序********************/
void delayms(unsigned int count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<850;j++);
}
//****************************************************************************************
//NRF24L01初始化
void init_NRF24L01(void)
{
delayms(1);
CE=0; // chip enable
CSN=1; // Spi disable
SCK=0; // Spi clock line init high
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 寫本地地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 寫接收端地址
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 頻道0自動 ACK應答允許
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允許接收地址只有頻道0
SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 設置信道為2.4GHZ,收發必須一致
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //設置接收數據長度,本次設置為32位元組
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //設置發射速率為1MHZ,發射功率為最大值0dB
}
//***************************************************************************************************
//函數:uint SPI_RW(uint uchar)
//功能:NRF24L01的SPI寫時序
//***************************************************************************************************/
uchar SPI_RW(uchar byte)
{
uchar i;
for(i=0;i<8;i++) // output 8-bit
{
MOSI = (byte & 0x80); // output 'uchar', MSB to MOSI
byte = (byte << 1); // shift next bit into MSB..
SCK = 1;
_nop_(); // Set SCK high..
byte |= MISO; // capture current MISO bit
SCK = 0; // ..then set SCK low again
_nop_();
}
return(byte); // return read uchar
}
//***************************************************************************************************
//函數:uchar SPI_Read(uchar reg)
//功能:NRF24L01的SPI時序
/****************************************************************************************************/
uchar SPI_Read(uchar reg)
{
uchar reg_val;
CSN = 0; // CSN low, initialize SPI communication...
SPI_RW(reg); // Select register to read from..
reg_val = SPI_RW(0); // ..then read registervalue
CSN = 1; // CSN high, terminate SPI communication
return(reg_val); // return register value
}
//***************************************************************************************************/
//功能:NRF24L01讀寫寄存器函數
//***************************************************************************************************/
uchar SPI_RW_Reg(uchar reg, uchar value)
{
uchar status;
CSN = 0; // CSN low, init SPI transaction
status = SPI_RW(reg); // select register
SPI_RW(value); // ..and write value to it..
CSN = 1; // CSN high again
return(status); // return nRF24L01 status uchar
}
//***************************************************************************************************/
//函數:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
//功能: 用於讀數據,reg:為寄存器地址,pBuf:為待讀出數據地址,uchars:讀出數據的個數
//***************************************************************************************************/
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar num)
{
uchar status,i;
CSN = 0; // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar
for(i=0;i<num;i++)
pBuf[i] = SPI_RW(0); //
CSN = 1;
return(status); // return nRF24L01 status uchar
}
//******************************************************************************************************
//函數:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
//功能: 用於寫數據:為寄存器地址,pBuf:為待寫入數據地址,uchars:寫入數據的個數
//******************************************************************************************************/
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar num)
{
uchar status,i;
CSN = 0; //SPI使能
status = SPI_RW(reg);
for(i=0; i<num; i++) //
SPI_RW(*pBuf++);
CSN = 1; //關閉SPI
return(status); //
}
//***************************************************************************************************/
//函數:void SetRX_Mode(void)
//功能:數據接收配置
//***************************************************************************************************/
void SetRX_Mode(void)
{
CE=0;
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收發完成中斷響應,16位CRC ,主接收
CE = 1;
delayms(1);
}
//*****************************************************************************************************/
//函數:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
//功能:數據讀取後放如rx_buf接收緩沖區中
/******************************************************************************************************/
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
unsigned char revale=0;
sta=SPI_Read(STATUS); // 讀取狀態寄存器來判斷數據接收狀況
if(RX_DR) // 判斷是否接收到數據
{
CE = 0; //SPI使能
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
revale =1; //讀取數據完成標志
}
SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到數據後RX_DR,TX_DS,MAX_PT都置高為1,通過寫1來清除中斷標志
return revale;
}
//*******************************************************************************************************
//函數:void nRF24L01_TxPacket(unsigned char * tx_buf)
//功能:發送 tx_buf中數據
//******************************************************************************************************/
void nRF24L01_TxPacket(unsigned char * tx_buf)
{
CE=0; //StandBy I模式
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 裝載接收端地址
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 裝載數據
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收發完成中斷響應,16位CRC,主發送
CE=1; //置高CE,激發數據發送
delayms(1);
}
//*******************************接收方主函數******************************************************
void main(void)
{
unsigned char TxBuf[20]={0};//
unsigned char RxBuf[20]={0};
unsigned char led_num,aa=0;
diola=1;
P1=0X0F;//幾個指示燈閃亮,沒實際作用
delayms(2000);
P1=0XF0;
delayms(2000);
P0=0XFF;//數碼管全關
weila=1;
weila=0;
init_NRF24L01() ;
while(1)
{
delayms(100);
SetRX_Mode(); // 接收模式 一直循環。
nRF24L01_RxPacket(RxBuf);
if(RX_DR==0) P1=~RxBuf[1];
}
}
//發射方主程序
void main(void)
{
unsigned char TxBuf[20]={0}; //
unsigned char RxBuf[20]={0};
unsigned char led_num;
delayms(100);
init_NRF24L01() ;
TxBuf[1] = 0x55 ;
delayms(100);
nRF24L01_TxPacket(TxBuf); // 第一次發
led1=0;
delayms(1000);
led1=1;
led_num=0x50;
while(1)
{
//init_NRF24L01() ;
if(KEY1 ==0 )
{
TxBuf[1] =led_num ;
led_num++;
nRF24L01_TxPacket(TxBuf); // 按下按鍵再發,可惜只能發一次
Delay(500);
}
}
}
3. nrf24l01無線模塊一個怎麼用
想nRF24L01與計算機連接,中間必須使用單片機。單片機負責操作nRF24L01,並通過串口等方式與計算機通訊。
如想直接接計算機請選用nRF24LU1