|
#include "Delay.h"
#include "nRF24L01.h"
#define Data_width 0x05 // 数据长度(可变1~32)
#define Addr_width 0x05 // 地址长度(固定为3,4,5)
uchar const TX_address[Addr_width] = {0x12,0x23,0x34,0x56,0xa5}; //发送机地址
uchar const RX_address[Addr_width] = {0x12,0x23,0x34,0x56,0xa5}; //接收机地址
/*******************************************************************************
* 函 数 名: nRF_port_init()
* 函数功能: 软件仿真SPI写命令字符
* 输 入: 需要写入的命令
* 输 出: nRF24L01+的状态量
*******************************************************************************/
void nRF_port_init()
{
//P0M0 = 0x00;
//P0M1 = 0x00;
nRF_CSN = 1; //低电平读写
nRF_CE = 0; //片选信号
nRF_MOSI = 0; //上升沿输入(芯片<=单片机)
nRF_SCK = 0; //时钟信号
nRF_IRQ = 1; //中断响应信号
nRF_MISO = 1;
}
/*******************************************************************************
* 函 数 名: uchar SPI_write(uchar cmd)
* 函数功能: 软件仿真SPI写命令字符
* 输 入: 需要写入的命令
* 输 出: nRF24L01+的状态量 2015-05-27测试通过
*******************************************************************************/
uchar SPI_write(uchar cmd) //[L35]
{
uchar i;
uchar sta = 0x00;
Delay_1us();
for(i=8;i>0;i--)
{
sta<<=1;
if((cmd & 0x80) == 0x80) //[L43]
nRF_MOSI = 1;
else
nRF_MOSI = 0;
Delay_1us();
nRF_SCK = 1; //上升沿写命令进入nRF
nRF_MISO =1; //读取之前先给端口赋值为‘1’
Delay_1us();
if(nRF_MISO == 1) //读状态寄存器status
sta +=1;
nRF_SCK = 0; //下降沿,读取状态寄存器
Delay_1us();
cmd<<=1;
}
return sta; //返回nRF的状态寄存器的值
}
/*******************************************************************************
* 函 数 名: uchar Read_byte(void)
* 函数功能: 读取SPI总线上的字节
* 输 入: 无
* 输 出: 读取的1Byte的数据 2015-05-27测试通过
*******************************************************************************/
uchar Read_byte(void)
{
uchar i,Data;
Data = 0xff;
for(i=8;i>0;i--)
{
Data<<=1; //左移一位
nRF_MOSI = 0;
nRF_SCK = 1; //上升沿不操作
Delay_1us();
nRF_MISO = 1; //端口赋值为1
Delay_1us();
if(nRF_MISO == 1) //读MISO引脚电平
Data +=1;
nRF_SCK = 0; //下降沿准备读数据
Delay_1us();
}
return Data;
}
/*******************************************************************************
* 函 数 名: uchar Write_byte(uchar Data)
* 函数功能: 向SPI总线上写数据
* 输 入: 写入的数据指针和字节数n
* 输 出: 无 2015-05-27测试通过
*******************************************************************************/
void Write_byte(uchar Data)
{
uchar i;
for(i=8;i>0;i--)
{
if((Data & 0x80) == 0x80)
nRF_MOSI = 1;
else
nRF_MOSI = 0;
Delay_1us();
nRF_SCK = 1; //上升沿
Delay_1us();
nRF_SCK = 0; //下降沿
Delay_1us();
Data<<=1;
}
}
/*******************************************************************************
* 函 数 名: uchar *Read_register(uchar cmd,uchar n)
* 函数功能: 读取可读寄存器的值
* 输 入: 寄存器地址,寄存器中数据的存储位置,读取的字节数
* 输 出: 字符的地址
* 说 明:----部分其他命令
RD_RX_PLOAD 0x61 // 读取接收数据指令
R_RX_PL_WID 0x60 // Read RX payload width for the top R_RX_PAYLOAD in the RX FIFO.
*******************************************************************************/
void Read_register(uchar cmd,uchar n,uchar *s) //[L121]
{
uchar i;
nRF_CSN = 0;
Delay_1us();
nRF_STATUS = SPI_write(cmd); //状态寄存器,并写入命令字符
for(i=0;i
{
*(s) = SPI_write(0xff);
Delay_1us();
s++;
}
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: uchar Read_reg(uchar cmd)
* 函数功能: 读取可读寄存器的值
* 输 入: 寄存器地址,寄存器中数据的存储位置,读取的字节数
* 输 出: 字符的地址
* 说 明:---所有的单字节寄存器(寄存器的地址),见[L160]
*******************************************************************************/
uchar Read_reg(uchar cmd)
{
uchar s;
nRF_CSN = 0;
Delay_1us();
nRF_STATUS = SPI_write(cmd); //状态寄存器,并写入命令字符
s = Read_byte();
nRF_CSN = 1;
Delay_1us();
return s;
}
/*******************************************************************************
* 函 数 名: void Write_reg_byte(uchar cmd,uchar ch)
* 函数功能: 写入命令给spi总线,并向寄存器中写一个字节的数据
* 输 入: 寄存器的地址,数据字符
* 输 出: 无
* 说 明: ---可写单字节寄存器,使用以下字节需要在加WRITE_REG
CONFIG2 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式
EN_AA 0x01 // 自动应答功能设置
EN_RXADDR 0x02 // 可用信道设置
SETUP_AW 0x03 // 收发地址宽度设置
SETUP_RETR 0x04 // 自动重发功能设置
RF_CH 0x05 // 工作频率设置
RF_SETUP 0x06 // 发射速率、功耗功能设置
STATUS 0x07 // 状态寄存器
RX_ADDR_P2 0x0C // 频道2接收数据地址
RX_ADDR_P3 0x0D // 频道3接收数据地址
RX_ADDR_P4 0x0E // 频道4接收数据地址
RX_ADDR_P5 0x0F // 频道5接收数据地址
RX_PW_P0 0x11 // 接收频道0接收数据长度
RX_PW_P1 0x12 // 接收频道0接收数据长度
RX_PW_P2 0x13 // 接收频道0接收数据长度
RX_PW_P3 0x14 // 接收频道0接收数据长度
RX_PW_P4 0x15 // 接收频道0接收数据长度
RX_PW_P5 0x16 // 接收频道0接收数据长度
DYNPD 0x1C // 动态预载值允许位
FEATURE 0x1D // 特殊功能寄存器
*******************************************************************************/
void Write_reg_byte(uchar cmd,uchar ch)
{
nRF_CSN = 0;
Delay_1us();
nRF_STATUS=SPI_write(cmd); //写指令地址
Write_byte(ch); //写数据
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: void Write_cmd_bytes(uchar cmd,uchar *s,uchar n)
* 函数功能: 向SPI总线写命令并附上字符串
* 输 入: 寄存器的地址,数据字符,字符串长度
* 输 出: 无
* 说 明:---寄存器地址(需要+WRITE_REG,三个多字节的寄存器)
RX_ADDR_P0 0x0A // 频道0接收数据地址
RX_ADDR_P1 0x0B // 频道1接收数据地址
TX_ADDR 0x10 // 发送地址寄存器
---命令代码(三个不可寻址的寄存器)
WR_TX_PLOAD 0xA0 // 写待发数据指令
W_ACK_PLOAD 0xA8 // 写ACK反馈数据包,USED in RX MODE.
W_TX_PLOAD_NACK 0xB0 // 只对该数据包不进行ACK反馈,USED in TX MODE.
*******************************************************************************/
void Write_cmd_bytes(uchar cmd,uchar *s,uchar n)
{
uchar i;
nRF_CSN = 0;
Delay_1us();
nRF_STATUS = SPI_write(cmd);
for(i=0;i
{
Write_byte(*(s+i));
}
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: void nRF_FLUSH_TX()
* 函数功能: 清空发射端的FIFO
* 输 入: 无
* 输 出: 无
*******************************************************************************/
void nRF_FLUSH_TX()
{
nRF_CSN = 0; //空闲状态下的CSN为1,SPI信号不可用
Delay_1us();
nRF_STATUS = SPI_write(FLUSH_TX);
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: void nRF_FLUSH_RX()
* 函数功能: 清空接收端的FIFO
* 输 入: 无
* 输 出: 无
*******************************************************************************/
void nRF_FLUSH_RX()
{
nRF_CSN = 0; //空闲状态下的CSN为1,SPI信号不可用
Delay_1us();
nRF_STATUS = SPI_write(FLUSH_RX);
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: nRF_NOP()
* 函数功能: 空操作
* 输 入: 无
* 输 出: 无
*******************************************************************************/
void nRF_NOP()
{
nRF_CSN = 0; //空闲状态下的CSN为1,SPI信号不可用
Delay_1us();
nRF_STATUS = SPI_write(NOP_n);
nRF_CSN = 1;
Delay_1us();
}
/*******************************************************************************
* 函 数 名: nRF_TX_init()
* 函数功能: 发射模式初始化nRF端口
* 输 入: 无
* 输 出: 无 2015-05-28调试成功
*******************************************************************************/
void nRF_TX_init()
{
nRF_CSN = 1; //空闲状态下的CSN为1,SPI信号不可用
nRF_SCK = 0; //空闲状态的SCK为0,无时钟信号
nRF_CE = 0; //初始状态CE为0
Write_cmd_bytes(WRITE_REG + TX_ADDR,TX_address,Addr_width); //写入发射地址,地址长度为5
Write_cmd_bytes(WRITE_REG + RX_ADDR_P0,RX_address,Addr_width);//写入ACK的接收地址
Write_reg_byte(WRITE_REG + EN_AA,0x01); // 频道0自动应答允许
Write_reg_byte(WRITE_REG + EN_RXADDR,0x01); // 允许接收地址只有频道0
Write_reg_byte(WRITE_REG + RF_CH,0x6e); // 设置信道工作为2.4GHZ,收发必须一致
Write_reg_byte(WRITE_REG + RX_PW_P0,Data_width); // 设置接收数据长度,本次设置为5字节
Write_reg_byte(WRITE_REG + RF_SETUP,0x07); // 设置发射速率为2MB/S,发射功率为最大值0dB
//Write_reg_byte(WRITE_REG + FEATURE,0x01); //允许无应答ACK信号返回
}
/*******************************************************************************
* 函 数 名: nRF_TX_packet()
* 函数功能: 发射模式发送数据包
* 输 入: 无
* 输 出: 返回发送状态 2015-05-28调试成功
*******************************************************************************/
uchar nRF_TX_packet()
{
uchar i;
Write_reg_byte(WRITE_REG + CONFIG2,0x4e); // 进入Stand—II
Write_reg_byte(WRITE_REG + STATUS,0xf0);
nRF_FLUSH_TX();
nRF_CE = 0;
Write_cmd_bytes(WR_TX_PLOAD,TX_buff,Data_width); //将数据发送到TX_FIFO中
//Write_cmd_bytes(W_TX_PLOAD_NACK,TX_buff,Data_width);//将数据发送到TX_FIFO,无ACK信号返回
nRF_CE = 1;
Delay_10us(); //延时10us等待数据发送
while(nRF_IRQ);
nRF_NOP();
//返回是否发送成功
switch((nRF_STATUS && 0x30))
{
case 0x20:i=0x00;break; //发送成功
case 0x10:i=0x01;break; //重发次数达到上限,发送失败
default:break;
}
Write_reg_byte(WRITE_REG + STATUS,nRF_STATUS); //状态标志位清零
return i; //返回发送状态
}
/*******************************************************************************
* 函 数 名 : nRF_RX_init()
* 函数功能 : 接收模式下初始化nRF端口
* 输 入 : 无
* 输 出 : 无 2015-05-28调试成功
*******************************************************************************/
void nRF_RX_init()
{
nRF_CSN = 1; //空闲状态下的CSN为1,SPI信号不可用
nRF_SCK = 0; //空闲状态的SCK为0,无时钟信号
nRF_CE = 0; //初始状态CE为0
Write_cmd_bytes(WRITE_REG + TX_ADDR,TX_address,Addr_width);//写入ACK的发送地址
Write_cmd_bytes(WRITE_REG + RX_ADDR_P0,RX_address,Addr_width);//写入ACK的接收地址
Write_reg_byte(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答允许
Write_reg_byte(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0
Write_reg_byte(WRITE_REG + RF_CH, 0x6e); // 设置信道工作为2.4GHZ,收发必须一致
Write_reg_byte(WRITE_REG + RX_PW_P0, Data_width); // 设置接收数据长度,本次设置为5字节
Write_reg_byte(WRITE_REG + RF_SETUP, 0x07); // 设置发射速率为2MB/S,发射功率为最大值0dB
}
/*******************************************************************************
* 函 数 名 : nRF_RX_packet()
* 函数功能 : 接收模式发送数据包
* 输 入 : 无
* 输 出 : 无 2015-05-28调试成功
*******************************************************************************/
void nRF_RX_packet()
{
Write_reg_byte(WRITE_REG + CONFIG2, 0x3f); // 进入RX MODE
nRF_CE = 1;
Delay_1ms(1000);
nRF_NOP();
if((nRF_IRQ == 0) &&((nRF_STATUS & 0x40) == 0x40))
{
Read_register(RD_RX_PLOAD,Data_width,RX_buff);
}
Write_reg_byte(WRITE_REG + STATUS,nRF_STATUS); //状态标志位清零
nRF_CE = 0;
nRF_FLUSH_RX();
}
|
|