/*功能:NRF24L01接收数据(单个开发板间)*/
/*更新:2017.4.11*/
/*开发板:CYHX-22*/
#include<STC12C5A60S2.h>//添加STC12头文件
#include<intrins.h>//添加51单片机库函数
#include"api.h" //添加NRF24L01寄存器库
sbit RFCS=P2^5;//NRF片选信号定义
sbit SCLK=P4^3;//NRF时钟线定义
sbit MISO=P4^2;//NRF数据线定义,主入从出
sbit MOSI=P4^1;//NRF数据线定义,主出从入
sbit RFINT=P2^2;//NRF中断信号
sbit RFCE=P4^0;//NRF模式控制线
sbit RFCS1=P1^5;//NRF1片选信号定义
sbit SCLK1=P0^4;//NRF1时钟线定义
sbit MISO1=P0^6;//NRF1数据线定义,主入从出
sbit MOSI1=P0^5;//NRF1数据线定义,主出从入
sbit RFINT1=P0^7;//NRF1中断信号
sbit RFCE1=P1^6;//NRF1模式控制线
#define TX_ADR_WIDTH 5 //5字节宽度的发送/接收地址
#define TX_PLOAD_WIDTH 4 //数据通道有效数据宽度
unsigned char code TX_ADDRESS[TX_ADR_WIDTH]={0X34,0X43,0X10,0X10,0X01};//定义一个静态发送地址
unsigned char RX_BUF[TX_PLOAD_WIDTH];//定义NRF数据接收缓存
unsigned char TX_BUF[TX_PLOAD_WIDTH]={0x55,0x55,0x55,0x55};//定义NRF数据发送缓存
unsigned char flag;//定义一个标记
unsigned char bdata sta; //定义一个特殊寄存器
void DelayUs(unsigned char); //声明us级延时函数
void DelayMs(unsigned char); //声明ms级延时函数
unsigned char SpiRw(unsigned char);//声明基本函数,完成GPIO模拟SPI的功能
unsigned char SpiRwReg(unsigned char,unsigned char);//声明寄存器访问函数
unsigned char SpiRead(unsigned char);//声明读取寄存器值的函数
unsigned char SpiReadBuf(unsigned char,unsigned char *,unsigned char);//声明接收缓冲区访问函数
unsigned char SpiWriteBuf(unsigned char,unsigned char *,unsigned char);//声明发射缓冲区访问函数
void RxMode(void);//声明配置接收模式函数
void TxMode(unsigned char *);//声明配置发送模式函数
unsigned char CheckAck(unsigned char);//声明应答位查询函数
void NrfSend(void);//声明NRF数据发送函数
void NrfRec(void);//声明NRF数据接收函数
unsigned char SpiRw1(unsigned char);//声明基本函数,完成GPIO模拟SPI的功能
unsigned char SpiRwReg1(unsigned char,unsigned char);//声明寄存器访问函数
unsigned char SpiRead1(unsigned char);//声明读取寄存器值的函数
unsigned char SpiReadBuf1(unsigned char,unsigned char *,unsigned char);//声明接收缓冲区访问函数
unsigned char SpiWriteBuf1(unsigned char,unsigned char *,unsigned char);//声明发射缓冲区访问函数
void RxMode1(void);//声明配置接收模式函数
void TxMode1(unsigned char *);//声明配置发送模式函数
unsigned char CheckAck1(unsigned char);//声明应答位查询函数
void NrfSend1(void);//声明NRF数据发送函数
void NrfRec1(void);//声明NRF数据接收函数
void IoInit(void);//声明NRFIO初始化函数
void UartInit(void);//声明串口初始化函数
int main() //主函数
{
IoInit();//NRF24L01 IO初始化
UartInit();//串口初始化
RxMode1();//配置成接收模式
while(1) //while(1)循环体
{
NrfSend();//NRF发送数据
NrfRec1();//NRF1接收数据
}
}
void DelayUs(unsigned char x) //定义us级延迟函数//STC12比STC89的速度快12倍,所以要注意延迟,当然要弄清楚时钟的确切含义。
{
unsigned char i;
while(x--)
for(i=0;i<12;i++)
_nop_();
}
void DelayMs(unsigned char x) //定义ms级延迟函数
{
unsigned char i;
while(x--)
for(i=0;i<250;i++)
DelayUs(4);
}
unsigned char SpiRw(unsigned char byte) //定义IO模拟SPI函数, 根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
{
unsigned char i;
for(i=0; i<8; i++) //循环8次
{
MOSI=(byte&0x80); // byte最高位输出到MOSI
byte<<=1; // 低一位移位到最高位
SCLK=1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
byte|=MISO; // 读MISO到byte最低位
SCLK=0; // SCK置低
}
return byte;
}
unsigned char SpiRwReg(unsigned char reg,unsigned char value) //定义寄存器访问函数,写数据value到reg寄存器
{
unsigned char status;
RFCS=0; //RFCS置低,开始传输数据
status=SpiRw(reg); //选择寄存器,同时发回状态字
SpiRw(value); //然后写数据到该寄存器
RFCS=1; //RFCS拉高,结束数据传输
return status; //返回状态寄存器
}
unsigned char SpiRead(unsigned char reg)//定义寄存器读取函数,从reg寄存器读取一字节
{
unsigned char regval;
RFCS=0; //RFCS置低,开始传输数据
SpiRw(reg); //选择寄存器
regval=SpiRw(0); //从该寄存器读取数据
RFCS=1; //RFCS拉高,结束数据传输
return regval; //返回寄存器数据
}
unsigned char SpiReadBuf(unsigned char reg,unsigned char *pbuf,unsigned char bytes) //接收缓冲区访问函数,从reg寄存器读出bytes个字节
{
unsigned char status,i;
RFCS=0; //CSN置低,开始传输数据
status=SpiRw(reg); //选择寄存器,同时返回状态字
for(i=0;i<bytes;i++)
pbuf[i]=SpiRw(0); //逐个字节从NRF读出
RFCS=1; //RFCS拉高,结束数据传输
return status; //返回状态寄存器
}
unsigned char SpiWriteBuf(unsigned char reg,unsigned char *pbuf,unsigned char bytes) //发射缓冲区访问函数,把缓存中的数据写入到哦NRF
{
unsigned char status ,i;
RFCS=0; //RFCS置低,开始传输数据
status=SpiRw(reg); //选择寄存器,同时返回状态字
for(i=0;i<bytes;i++)
SpiRw(pbuf[i]); //逐个写入NRF
RFCS=1; //拉高RFCS,结束数据传输
return status; //返回状态寄存器
}
void RxMode() //配置为接收模式,等待接收发送设备的数据包
{
RFCE=0;
DelayUs(200);
SpiWriteBuf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址
SpiRwReg(WRITE_REG + EN_AA, 0x01); //使能接收通道0自动应答
SpiRwReg(WRITE_REG + EN_RXADDR, 0x01); //使能接收通道
SpiRwReg(WRITE_REG + RF_CH, 40); //选择射频通道0x40
SpiRwReg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); //接收通道0选择和发送通道相同有效数据宽度
SpiRwReg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps,发送功率0dBm,低噪声放大器增益
SpiRwReg(WRITE_REG + CONFIG, 0x0f); //CRC使能,16位CRC校验,上电,接收模式
RFCE=1; //拉高CE启动接收设备
}
void TxMode(unsigned char *buf) //配置发射模式函数,130us后启动发射,数据发送结束后,发送模块自动转入接收模式等待应答信号
{
RFCE=0;
SpiWriteBuf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); //写入发送地址
SpiWriteBuf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //为了应答接收设备,接收通道0地址和发送地址相同
SpiWriteBuf(WR_TX_PLOAD, buf, TX_PLOAD_WIDTH); //写数据包到TX FIFO
SpiRwReg(WRITE_REG + EN_AA, 0x01); //使能接收通道0自动应答
SpiRwReg(WRITE_REG + EN_RXADDR, 0x01); //使能接收通道0
SpiRwReg(WRITE_REG + SETUP_RETR, 0x0a); //自动重发延时等待250us+86us,自动重发10次
SpiRwReg(WRITE_REG + RF_CH, 40); //选择射频通道0x40
SpiRwReg(WRITE_REG + RF_SETUP, 0x07); //数据传输率1Mbps,发射功率0dBm,低噪声放大增益
SpiRwReg(WRITE_REG + CONFIG, 0x0e); //CRC使能,16位CRC校验,上电
RFCE=1;
DelayUs(120);
}
unsigned char CheckAck(unsigned char clear) //应答查询函数,检查接收设备有无接收到数据包,设定没有收到应答信
{
while(RFINT);
sta=SpiRw(NOP); //返回状态寄存器
if(sta&0x10)
if(clear) //是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发
SpiRw(FLUSH_TX);
SpiRwReg(WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
RFINT=1;
if(sta&0x20)
return 0x00;
else
return 0xff;
}
void NrfSend() //定义数据发送函数
{
TxMode(TX_BUF);
CheckAck(1);
}
void NrfRec() //定义数据接收函数
{
RxMode(); //NRF配置为接收模式
DelayUs(150);//延时约150us
sta=SpiRead(STATUS);//读取NRF状态寄存器
if(0x40&sta) //读取NRF状态寄存器的第6位,判断是否接收到数据
{
SpiReadBuf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);//
flag=1; //标志位置位
}
SpiRwReg(WRITE_REG+STATUS,sta);
if(flag)
{
flag=0; //标志位清0
DelayMs(250); //延时约250ms
DelayMs(250); //延时约250ms
}
}
unsigned char SpiRw1(unsigned char byte) //定义IO模拟SPI函数, 根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01
{
unsigned char i;
for(i=0; i<8; i++) //循环8次
{
MOSI1=(byte&0x80); // byte最高位输出到MOSI1
byte<<=1; // 低一位移位到最高位
SCLK1=1; // 拉高SCK,nRF24L01从MOSI1读入1位数据,同时从MISO1输出1位数�