#include <reg52.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned char uint;
sbit
sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)
sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)
sbit SCK
sbit CE
sbit CSN =P2^2; //数字输入(SPI片选信号)
sbit IRQ =P2^6; //数字输入(可屏蔽中断)
sbit KEY1=P3^3;//按键S1
sbit KEY2=P3^2;//按键S2
sbit led1=P1^0; //LED0
sbit led2=P1^1; //LED1
sbit
sbit
sbit
#define TX_ADR_WIDTH
#define RX_ADR_WIDTH
#define TX_PLOAD_WIDTH
#define RX_PLOAD_WIDTH
uint const TX_ADDRESS[TX_ADR_WIDTH]=
{0x34,0x43,0x10,0x10,0x01}; //本地地址
uint const RX_ADDRESS[RX_ADR_WIDTH]=
{0x34,0x43,0x10,0x10,0x01}; //接收地址
#define READ_REG
#define WRITE_REG
#define RD_RX_PLOAD
#define WR_TX_PLOAD
#define FLUSH_TX
#define FLUSH_RX
#define REUSE_TX_PL
#define NOP
#define CONFIG
#define EN_AA
#define EN_RXADDR
#define SETUP_AW
#define SETUP_RETR
#define RF_CH
#define RF_SETUP
#define STATUS
#define OBSERVE_TX
#define CD
#define RX_ADDR_P0
#define RX_ADDR_P1
#define RX_ADDR_P2
#define RX_ADDR_P3
#define RX_ADDR_P4
#define RX_ADDR_P5
#define TX_ADDR
#define RX_PW_P0
#define RX_PW_P1
#define RX_PW_P2
#define RX_PW_P3
#define RX_PW_P4
#define RX_PW_P5
#define FIFO_STATUS
void Delay(unsigned int s);
void inerDelay_us(unsigned char n); //小延时
void init_NRF24L01(void);
uint SPI_RW(uint dat);
uchar SPI_Read(uchar reg);
void SetRX_Mode(void);
uint SPI_RW_Reg(uchar reg, uchar value);
uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);
uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);
//把pBuf缓存中的数据写入到nRF24L01,通常用来写入发
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);
void nRF24L01_TxPacket(unsigned char * tx_buf);
void Delay(unsigned int s)
{
unsigned int i;
for(i=0; i<s; i++);
for(i=0; i<s; i++);
}
uint bdata sta;
sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位
sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位
sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位
void inerDelay_us(unsigned char n) //延时,us 级
{
for(;n>0;n--)
_nop_();
}
void init_NRF24L01(void)
{
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);
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);
SPI_RW_Reg(WRITE_REG + RF_CH, 0);
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
//设置接收数据长度,本次设置为32字节
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);
}
uint SPI_RW(uint dat)
{
uint i;
MOSI = (dat & 0x80);
dat = (dat << 1);
SCK = 1;
dat |= MISO;
SCK = 0;
}
uchar SPI_Read(uchar reg)
{
uchar reg_val;
CSN = 0;
SPI_RW(reg);
reg_val = SPI_RW(0); //然后从该寄存器读数据
CSN = 1;
return(reg_val);
}
uint SPI_RW_Reg(uchar reg, uchar value)
{
uchar status;
CSN = 0;
status = SPI_RW(reg);
SPI_RW(value);
CSN = 1;
return(status);
}
uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
{
uint status,i;
CSN = 0;
status = SPI_RW(reg);
for(i=0;i<uchars;i++)
pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出
CSN = 1;
return(status);
}
uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)
{
uint status,i;
CSN = 0;
status = SPI_RW(reg);
inerDelay_us(10);
for(i=0; i<uchars; i++)
SPI_RW(*pBuf++); //逐个字节写入nRF24L01
CSN = 1;
return(status);
}
void SetRX_Mode(void)
{
CE=0;
SPI_RW_Reg(WRITE_REG + CONFIG,
0x0f);//CRC使能,16位CRC校验,上电,接收模式
CE = 1;
inerDelay_us(130);
}
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
{
sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
if(RX_DR) // 判断是否接收到数据
{
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);
return revale;
}
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);
CE=1; //置高CE,激发数据发送
inerDelay_us(10);
}
void main(void)
{
unsigned char tf =0;
unsigned char TxBuf[20]={0}; // 要发送的数组
unsigned char RxBuf[20]={0}; // 接收的数据 数组
led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭
Delay(1000);
while(1)
{
led1=0; //本地led 灯闪烁
Delay(200);
led1=1;
Delay(200);
TxBuf[2] =1 ; //赋值
tf = 1 ;
led2=0; //本地led 灯闪烁
Delay(200);
led2=1;
Delay(200);
nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer data
TxBuf[1] = 0x00; //清零
TxBuf[2] = 0x00;
tf=0;
Delay(1000);
SetRX_Mode();
RxBuf[1] = 0x00;
RxBuf[2] = 0x00;
nRF24L01_RxPacket(RxBuf);
{
if( RxBuf[1]==1)
{
}
if( RxBuf[2]==1)
{
led4=RxBuf[4];
}
Delay(3000); //old is '1000'
}
RxBuf[1] = 0x00;
RxBuf[2] = 0x00;
led3=1;
led4=1;
}
}
本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。
对部分函数的解释:
uint SPI_RW(uint
dat)
同时将输入字节(MISO)从
LSB 循环移入。上升沿读入,下降沿输出。 (从 SCK被初始化
为低电平可以判断出)
uchar SPI_Read(uchar
reg);
寄存器中的值读出来。对于函数来说也就是把 reg 寄存器的值读到 reg_val 中去。
uint
SPI_RW_Reg(uchar reg, uchar
value);
就是
0x20+寄存器地址)把要设定的值写到相应的寄存器地址里面去,并读取返回值。对于
函数来说也就是把
value值写到 reg 寄存器中。
需要注意的是,访问
NRF24L01 之前首先要 enable 芯片(CSN=0; ) ,访问完了以后再 disable
芯片(CSN=1;
)。
uint
SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars);
READ_REG命令把数据从接收
FIFO(RD_RX_PLOAD)中读出并存到数组里面去。
uint
SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars);
//把pBuf缓存中的数据写入到nRF24L01,通常
发射缓冲区访问函数:主要用来把数组里的数放到发射 FIFO缓冲区中。基本思路就是通过
WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去。
Tx
1)写 Tx 节点的地址 TX_ADDR
2)写 Rx 节点的地址(主要是为了使能 Auto Ack)
RX_ADDR_P0
3)使能 AUTO ACK EN_AA
4)使能 PIPE 0 EN_RXADDR
5)配置自动重发次数 SETUP_RETR
6)选择通信频率 RF_CH
7)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP
8 )
9)配置 24L01 的基本参数以及切换工作模式 CONFIG。
Rx 模式初始化过程:
初始化步骤 24L01 相关寄存器
1)写 Rx 节点的地址 RX_ADDR_P0
2)使能 AUTO ACK EN_AA
3)使能 PIPE 0 EN_RXADDR
4)选择通信频率 RF_CH
5)
6)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP
7)配置 24L01 的基本参数以及切换工作模式 CONFIG。
|
|