NRF24L01简介
nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型“SchockBurst”模式控制器、功率放大器、晶体振荡器、调制器和解调器。
最大的优点,就是便宜,且功能强大
实际操作
整体使用标准SPI协议进行读写访问
通过NRF24L01设置内部寄存器来设置参数,最后上电启动即可
其中SPI指令包括:
寄存器地址:
芯片手册的配置流程
源码分享
将寄存器地址定义,封装为头文件
引脚根据实际情况自定义
#ifndef _API_DEF_
#define _API_DEF_
// Dpin
sbit CSN = P1^3 ;
sbit CE = P1^2 ;
sbit SCK = P1^7 ;
sbit MOSI= P1^1 ;
sbit MISO= P1^6 ;
sbit IRQ = P1^4 ;
// commands
#define READ_REG 0x00
#define WRITE_REG 0x20
#define RD_RX_PLOAD 0x61
#define WR_TX_PLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define NOP 0xFF
// registers
#define CONFIG 0x00
#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
#define RX_ADDR_P1 0x0B
#define RX_ADDR_P2 0x0C
#define RX_ADDR_P3 0x0D
#define RX_ADDR_P4 0x0E
#define RX_ADDR_P5 0x0F
#define TX_ADDR 0x10
#define RX_PW_P0 0x11
#define RX_PW_P1 0x12
#define RX_PW_P2 0x13
#define RX_PW_P3 0x14
#define RX_PW_P4 0x15
#define RX_PW_P5 0x16
#define FIFO_STATUS 0x17
#endif /* _API_DEF_ */
与实际代码
#include<reg52.h>
#include"nRFreg.h"
#define ADDR_LEN 5 // 5字节宽度的发送/接收地址
#define DATA_LEN 4 // 数据通道有效数据宽度(每次发送的字节数)
// 接收用m1,发送机用m2
unsigned char code MyAddr1[ADDR_LEN] = {0x34,0x41,0x11,0x11,0x01};
unsigned char code MyAddr2[ADDR_LEN] = {0x34,0x41,0x10,0x10,0x01};
unsigned char RxBuf[DATA_LEN];
unsigned char TxBuf[DATA_LEN];
unsigned char sta ; //此变量用来存储STATUS状态字
#define RX_DR sta^0x40
#define TX_DS sta^0x20
#define MAX_RT sta^0x10
/**************************************************
init_io()
初始化IO
/**************************************************/
void init_io(void) {
CE = 0; // 待机
CSN = 1; // SPI禁止
SCK = 0; // SPI时钟置低
IRQ = 1; // 中断复位
}
/**************************************************/
/**************************************************
delay_ms()
延迟
/**************************************************/
void delay(unsigned char x) {
unsigned char y ;
for ( ; x > 0 ; x-- )
for ( y = 110 ; y > 0 ; y-- ) ;
}
/**************************************************/
/**************************************************
SPI_RW()
根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节
/**************************************************/
unsigned char SPI_RW(unsigned char byte) {
unsigned char i;
for(i=0; i<8; i++) {
MOSI = (byte & 0x80); // byte最高位输出到MOSI
byte <<= 1; // 低一位移位到最高位
SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
byte |= MISO; // 读MISO到byte最低位
SCK = 0; // SCK置低
}
return byte ; // 返回读出的一字节
}
/**************************************************/
/**************************************************
SPI_RW_Reg()
写数据value到reg寄存器
/**************************************************/
unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value) {
unsigned char status;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
SPI_RW(value); // 然后写数据到该寄存器
CSN = 1; // CSN拉高,结束数据传输
return status ; // 返回状态寄存器
}
/**************************************************/
/**************************************************
SPI_Read()
从reg寄存器读一字节
/**************************************************/
unsigned char SPI_Read(unsigned char reg) {
unsigned char reg_val;
CSN = 0; // CSN置低,开始传输数据
SPI_RW(reg); // 选择寄存器
reg_val = SPI_RW(0); // 然后从该寄存器读数据
CSN = 1; // CSN拉高,结束数据传输
return reg_val ; // 返回寄存器数据
}
/**************************************************/
/**************************************************
SPI_Read_Buf()
从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址
/**************************************************/
unsigned char SPI_Read_Buf(unsigned char reg, unsigned char * pBuf, unsigned char bytes) {
unsigned char status, i;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
pBuf[i] = SPI_RW(0); // 逐个字节从nRF24L01读出
CSN = 1; // CSN拉高,结束数据传输
return status ; // 返回状态寄存器
}
/**************************************************/
/**************************************************
SPI_Write_Buf()
把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址
/**************************************************/
unsigned char SPI_Write_Buf(unsigned char reg, unsigned char * pBuf, unsigned char bytes) {
unsigned char status, i;
CSN = 0; // CSN置低,开始传输数据
status = SPI_RW(reg); // 选择寄存器,同时返回状态字
for(i=0; i<bytes; i++)
SPI_RW(pBuf[i]); // 逐个字节写入nRF24L01
CSN = 1; // CSN拉高,结束数据传输
return status ; // 返回状态寄存器
}
/**************************************************/
/**************************************************
RX_Mode()
这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包
/**************************************************/
void RX_Mode(void) {
CE = 0;
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 自动应答
SPI_RW_Reg(WRITE_REG + SETUP_AW , 0x03 ) ; //地址宽度
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率,发射功率,低噪声放大器增益
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, MyAddr1, ADDR_LEN); // 接收设备通道0地址设置为
SPI_RW_Reg(WRITE_REG + RX_PW_P0, DATA_LEN); // 接收通道宽度设置 ( 4 )
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); //接收数据通道0允许
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式
CE = 1; // 拉高CE启动接收设备
}
/**************************************************/
/**************************************************
TX_Mode()
这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),
130us后启动发射.注意,数据发送结束后,发送模块自动转入接收模式等待应答信号。
/**************************************************/
void TX_Mode(unsigned char * BUF , unsigned char * ToAddr , unsigned char CH ) {
CE = 0;
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发
SPI_RW_Reg(WRITE_REG + SETUP_AW , 0x03 ) ; //地址宽度
SPI_RW_Reg(WRITE_REG + RF_CH, CH); // 选择射频通道0x40
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率,发射功率,低噪声放大器增益
SPI_RW_Reg(WRITE_REG + CONFIG, 0x02); // 上电
SPI_Write_Buf(WRITE_REG + TX_ADDR, ToAddr, ADDR_LEN); // 写入发送的通道地址
SPI_Write_Buf(WR_TX_PLOAD, BUF, DATA_LEN); // 将数据(BUF)写入TF FIFO
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电
CE = 1;
}
/**************************************************/
/**************************************************
Check_ACK()
检查接收设备有无接收到数据包,
/*************************************************/
unsigned char Check_ACK(void) { // 收到应答信号返回0,反之 ; clear为1,不重发数据,为0相反
while(IRQ); //默认情况下(当前情况就是默认),发送/接收数据之后IRQ位会置0
sta = SPI_RW(NOP); // 返回状态寄存器
if(MAX_RT) { // 如果触发重发次数溢出
SPI_RW_Reg(WRITE_REG + STATUS, sta) ; // 清除TX_DS和MAX_RT中断标志
SPI_RW(FLUSH_TX) ;
return 1 ;
}
if(TX_DS) {
SPI_RW_Reg(WRITE_REG + STATUS, sta) ;
return 0 ;
}
}
/**************************************************/
int i = 1 ;
/**************
//接收方
void main(void) {
P2 = 0xff ;
init_io();
RX_Mode();
while (!IRQ) {
SPI_Read_Buf(RD_RX_PLOAD, RxBuf, DATA_LEN);
P2 = RxBuf[0] ;
sta = SPI_RW(NOP) ;
SPI_RW_Reg( WRITE_REG + STATUS , sta ) ;
while (1) {
i %= 4 ;
i += 1 ;
delay(1000);delay(1000);delay(1000);
P2 = RxBuf[i] ;
}
}
}
/**************/
/**************
//发送---------------------------------------------------------------
void main(void) {
init_io() ;
RX_Mode();
TxBuf[3] = 0x09 ;
TxBuf[2] = 0x01+2 ;
TxBuf[1] = 0x01+1 ;
TxBuf[0] = 0xc0 ;
delay(10) ;
TX_Mode( TxBuf , MyAddr1 , 40 ) ;
while (1) ;
}
/**************/
测试
试验机参数:
接收机:STC89C52RC + NRF24L01
发送机:STC89C52 + NRF24L01 + 电源(NRF24L01工作与3.0~3.7v)
可以正常使用