最近用STC的单片机做了个遥控小车,遥控器和小车主控板用的都是STC的单片机,使用NRF24L01无线通信。本文简单记录下使用单片机的硬件SPI对无线模块进行配置,从而实现通信的过程。
一、单片机型号
由于是遥控小车,那么无线通信就必须是一对的。分为发送端与接收端。
发送端使用的是STC8H4K64TL,封装:TSSOP20
接收端使用的是STC12C5A32S2,封装:LQFP48
二、系统工作频率
发送端:使用STC-ISP软件进行配置,选择22.1184MHZ(该频率下串口也可以正常使用)
如下图
接收端:使用12M外部晶振
三、发送端程序的初始化配置
STC为STC8H单片机开发了库函数,免去了以往繁琐的寄存器配置的工作。
1.库函数如何下载
下载的方式有两种:
1、可以直接通过STC-ISP软件下载,如下图
2、登陆STC官网下载,网址如下:
2.库函数如何使用
库函数下载完成后,文件夹内有独立例程、库函数、综合例程3个文件夹,综合例程文件夹内有库函数使用说明。
个人建议直接在官方独立例程上进行二次开发。
我的遥控器上使用了单片机的AD、定时器、串口、SPI、IO等资源,上述资源的配置全都使用的是官方的库函数进行配置。
NRF24L01无线通信,网上有很多的案例,非常好也很实用。大部分使用的是软件模拟的SPI时序。本篇文章重点说明一下不使用模拟方式,而是使用单片机的本身自带的SPI如何完成配置。
下面是使用库函数配置SPI的代码。
/*************** SPI初始化函数 *****************/
void SPI_config(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Enable = ENABLE;//ENABLE,DISABLE
SPI_InitStructure.SPI_SSIG = ENABLE;//ENABLE, DISABLE
SPI_InitStructure.SPI_FirstBit = SPI_MSB;//SPI_MSB, SPI_LSB
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//SPI_Mode_Master, SPI_Mode_Slave
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//SPI_CPOL_High, SPI_CPOL_Low
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //SPI_CPHA_1Edge, SPI_CPHA_2Edge
SPI_InitStructure.SPI_Speed = SPI_Speed_4; //SPI_Speed_4,SPI_Speed_16,SPI_Speed_64,SPI_Speed_128
SPI_Init(&SPI_InitStructure);
NVIC_SPI_Init(DISABLE,Priority_2);//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
SPI_SW(SPI_P12_P13_P14_P15);
}
上述代码中,SPI设置为主机模式。单片机为主机,NRF24L01为从机。即官方手册上的单主单从模式。
这里请注意,STC官方提供的SPI库函数有点问题,我在配置完成后,始终无法正常通信,最终检查发现是库函数有问题。
官方提供的代码
//========================================================================
// 函数: void SPI_Init(SPI_InitTypeDef *SPIx)
// 描述: SPI初始化程序.
// 参数: SPIx: 结构参数,请参考spi.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void SPI_Init(SPI_InitTypeDef *SPIx)
{
if(SPIx->SPI_SSIG == ENABLE) SPCTL &= ~(1<<7); //enable SS, conform Master or Slave by SS pin.
else SPCTL |= (1<<7); //disable SS, conform Master or Slave by SPI_Mode
SPI_Start(SPIx->SPI_Enable);
SPI_FirstBit_Set(SPIx->SPI_FirstBit);
SPI_Mode_Set(SPIx->SPI_Mode);
SPI_CPOL_Set(SPIx->SPI_CPOL);
SPI_CPHA_Set(SPIx->SPI_CPHA);
SPI_Clock_Select(SPIx->SPI_Speed);
SPI_RxTimerOut = 0;
B_SPI_Busy = 0;
}
函数内第1行,如SSIG使能,则需在SPCTL的第7位赋1。主机模式下时,即SPCTL的第4位赋1,从机模式下时,MSTR赋0。由此可见,库函数刚好搞反了。
下面是我修改后的代码。
//========================================================================
// 函数: void SPI_Init(SPI_InitTypeDef *SPIx)
// 描述: SPI初始化程序.
// 参数: SPIx: 结构参数,请参考spi.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void SPI_Init(SPI_InitTypeDef *SPIx)
{
if(SPIx->SPI_SSIG == ENABLE)
SPCTL |= (1<<7);//enable SS, conform Master or Slave by SS pin.
else
SPCTL &= ~(1<<7); //disable SS, conform Master or Slave by SPI_Mode
//SPI_SSIG_Set(SPIx->SPI_SSIG);
SPI_Start(SPIx->SPI_Enable);
SPI_FirstBit_Set(SPIx->SPI_FirstBit);
SPI_Mode_Set(SPIx->SPI_Mode);
SPI_CPOL_Set(SPIx->SPI_CPOL);
SPI_CPHA_Set(SPIx->SPI_CPHA);
SPI_Clock_Select(SPIx->SPI_Speed);
SPI_RxTimerOut = 0;
B_SPI_Busy = 0;
}
其实也可以将下面代码中前四行注释掉,第五行取消注释功能是一样的。
//========================================================================
// 函数: void SPI_Init(SPI_InitTypeDef *SPIx)
// 描述: SPI初始化程序.
// 参数: SPIx: 结构参数,请参考spi.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void SPI_Init(SPI_InitTypeDef *SPIx)
{
// if(SPIx->SPI_SSIG == ENABLE)
// SPCTL |= (1<<7);//enable SS, conform Master or Slave by SS pin.
// else
// SPCTL &= ~(1<<7); //disable SS, conform Master or Slave by SPI_Mode
SPI_SSIG_Set(SPIx->SPI_SSIG);
SPI_Start(SPIx->SPI_Enable);
SPI_FirstBit_Set(SPIx->SPI_FirstBit);
SPI_Mode_Set(SPIx->SPI_Mode);
SPI_CPOL_Set(SPIx->SPI_CPOL);
SPI_CPHA_Set(SPIx->SPI_CPHA);
SPI_Clock_Select(SPIx->SPI_Speed);
SPI_RxTimerOut = 0;
B_SPI_Busy = 0;
}
其实上述代码的配置,总结起来就是两行代码
SPSTAT |= 0XC0;
SPCTL = 0XD0;
四、接收端程序的初始化配置
其实接收端的代码配置和发送端是一样的,SPI的初始化配置可以直接使用上述两行代码。但是还是希望要仔细查阅官方的手册,明确每个寄存器的意义。
SPSTAT |= 0XC0;
SPCTL = 0XD0;
五、发送端代码
#include "nrf24l01.H"
#include "STC8G_H_SPI.h"
#include "STC8G_H_Delay.h"
const u8 TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
const u8 RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
u8 send_buf[TX_PLOAD_WIDTH]; //26+6
u8 recv_buf[RX_PLOAD_WIDTH];
/**********************/
/* 初始化硬件SPI口,此部分代码由STC官方SPI库函数代替 */
/**********************/
//void SPI_Init(void)
//{
// NRF_CE=0;
// NRF_CSN=1;
// NRF_SCK=0;
// NRF_IRQ=1;
//下述两行代码取消注释,表示使用硬件SPI驱动
// SPSTAT |= 0XC0;
// SPCTL = 0XD0;
//}
/**********************/
/* SPI数据收发函数(硬件SPI),此部分代码由STC官方SPI库函数代替 */
/**********************/
//u8 SPI_RW(u8 tr_data)
//{
// u8 i=0;
// SPSTAT |= 0Xc0; // 清高两位,
// SPDAT=tr_data;
// while(((SPSTAT&0X80)!=0X80)&&(i<20))
// {
// i++;
// delay_ms(1);
// }
// return SPDAT;
//}
// 下面是“模拟SPI”
// u8 SPI_RW(u8 byte)
// {
// u8 bit_ctr;
// for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 输出8位
// {
// NRF_MOSI=(byte&0x80); // MSB TO MOSI
// byte=(byte<<1); // shift next bit to MSB
// NRF_SCK=1;
// byte|=NRF_MISO; // capture current MISO bit
// NRF_SCK=0;
// }
// return byte;
// }
/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* value 给寄存器写的值 */
/* 出口参数:status 状态值 */
/*********************************************/
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
u8 status;
NRF_CSN=0; //CSN=0;
status = SPI_RW(reg);//发送寄存器地址,并读取状态值
SPI_RW(value);
NRF_CSN=1; //CSN=1;
return status;
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节) */
/* 入口参数:reg 要读的寄存器地址 */
/* 出口参数:value 读出寄存器的值 */
/*************************************************/
u8 NRF24L01_Read_Reg(u8 reg)
{
u8 value;
NRF_CSN=0; //CSN=0;
SPI_RW(reg);//发送寄存器值(位置),并读取状态值
value = SPI_RW(NOP_1);
NRF_CSN=1; //CSN=1;
return value;
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节) */
/* 入口参数:reg 寄存器地址 */
/* *pBuf 读出寄存器值的存放数组 */
/* len 数组字节长度 */
/* 出口参数:status 状态值 */
/*********************************************/
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 status,u8_ctr;
NRF_CSN=0; //CSN=0
status=SPI_RW(reg);//发送寄存器地址,并读取状态值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
pBuf[u8_ctr]=SPI_RW(0XFF);//读出数据
NRF_CSN=1; //CSN=1
return status; //返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* *pBuf 值的存放数组 */
/* len 数组字节长度 */
/**********************************************/
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
u8 status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//发送寄存器值(位置),并读取状态值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //写入数据
NRF_CSN=1;
return status; //返回读到的状态值
}
/*********************************************/
/* 函数功能:24L01接收数据 */
/* 入口参数:rxbuf 接收数据数组 */
/* 返回值: 0 成功收到数据 */
/* 1 没有收到数据 */
/*********************************************/
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 state;
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&RX_OK)//接收到数据
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式 */
/* 入口参数:txbuf 发送数据数组 */
/* 返回值; 0x10 达到最大重发次数,发送失败*/
/* 0x20 成功发送完成 */
/* 0xff 发送失败 */
/**********************************************/
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 state;
NRF_CE=0;//CE拉低,使能24L01配置
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节
NRF_CE=1;//CE置高,使能发送
while(NRF_IRQ==1);//等待发送完成
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(state&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//发送失败
}
/********************************************/
/* 函数功能:检测24L01是否存在 */
/* 返回值; 0 存在 */
/* 1 不存在 */
/********************************************/
u8 NRF24L01_Check(void)
{
u8 check_in_buf[5]= {0x11,0x22,0x33,0x44,0x55};
u8 check_out_buf[5]= {0x00};
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
if((check_out_buf[0] == 0x11)&&\
(check_out_buf[1] == 0x22)&&\
(check_out_buf[2] == 0x33)&&\
(check_out_buf[3] == 0x44)&&\
(check_out_buf[4] == 0x55))return 0;
else return 1;
}
void NRF24L01_TX_Mode(void)
{
NRF_CE=0;
//NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
//NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通道为125
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0F); //7db增益,250kbps
//NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 (两边的速率一定要一样!!!!)
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0E); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断
NRF_CE=1; //CE置高
}
void NRF24L01_RX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通信频率
NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
delay_ms(150);
NRF_CE = 1; //CE为高,进入接收模式
}
六、接收端代码
#include "nrf24l01.H"
#include "delay.H"
const BYTE TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
const BYTE RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
BYTE send_buf[TX_PLOAD_WIDTH]; //26+6
BYTE recv_buf[RX_PLOAD_WIDTH];
/**********************/
/* 初始化硬件SPI口 */
/**********************/
void SPI_Init(void)
{
// NRF_CE=0;
// NRF_CSN=1;
// NRF_SCK=0;
// NRF_IRQ=1;
//下述两行代码取消注释,表示使用硬件SPI驱动
SPSTAT |= 0XC0;
SPCTL = 0XD0;
}
/**********************/
/* SPI数据收发函数(硬件SPI) */
/**********************/
BYTE SPI_RW(BYTE tr_data)
{
BYTE i=0;
SPSTAT |= 0Xc0; // 清高两位,
SPDAT=tr_data;
while(((SPSTAT&0X80)!=0X80)&&(i<20))
{
i++;
delay_ms(1);
}
return SPDAT;
}
// 下面是“模拟SPI”
// BYTE SPI_RW(BYTE byte)
// {
// BYTE bit_ctr;
// for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 输出8位
// {
// NRF_MOSI=(byte&0x80); // MSB TO MOSI
// byte=(byte<<1); // shift next bit to MSB
// NRF_SCK=1;
// byte|=NRF_MISO; // capture current MISO bit
// NRF_SCK=0;
// }
// return byte;
// }
/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* value 给寄存器写的值 */
/* 出口参数:status 状态值 */
/*********************************************/
BYTE NRF24L01_Write_Reg(BYTE reg,BYTE value)
{
BYTE status;
NRF_CSN=0; //CSN=0;
status = SPI_RW(reg);//发送寄存器地址,并读取状态值
SPI_RW(value);
NRF_CSN=1; //CSN=1;
return status;
}
/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节) */
/* 入口参数:reg 要读的寄存器地址 */
/* 出口参数:value 读出寄存器的值 */
/*************************************************/
BYTE NRF24L01_Read_Reg(BYTE reg)
{
BYTE value;
NRF_CSN=0; //CSN=0;
SPI_RW(reg);//发送寄存器值(位置),并读取状态值
value = SPI_RW(NOP);
NRF_CSN=1; //CSN=1;
return value;
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节) */
/* 入口参数:reg 寄存器地址 */
/* *pBuf 读出寄存器值的存放数组 */
/* len 数组字节长度 */
/* 出口参数:status 状态值 */
/*********************************************/
BYTE NRF24L01_Read_Buf(BYTE reg,BYTE *pBuf,BYTE len)
{
BYTE status,u8_ctr;
NRF_CSN=0; //CSN=0
status=SPI_RW(reg);//发送寄存器地址,并读取状态值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
pBuf[u8_ctr]=SPI_RW(0XFF);//读出数据
NRF_CSN=1; //CSN=1
return status; //返回读到的状态值
}
/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节) */
/* 入口参数:reg 要写的寄存器地址 */
/* *pBuf 值的存放数组 */
/* len 数组字节长度 */
/**********************************************/
BYTE NRF24L01_Write_Buf(BYTE reg, BYTE *pBuf, BYTE len)
{
BYTE status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//发送寄存器值(位置),并读取状态值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //写入数据
NRF_CSN=1;
return status; //返回读到的状态值
}
/*********************************************/
/* 函数功能:24L01接收数据 */
/* 入口参数:rxbuf 接收数据数组 */
/* 返回值: 0 成功收到数据 */
/* 1 没有收到数据 */
/*********************************************/
BYTE NRF24L01_RxPacket(BYTE *rxbuf)
{
BYTE state;
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&RX_OK)//接收到数据
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//没收到任何数据
}
/**********************************************/
/* 函数功能:设置24L01为发送模式 */
/* 入口参数:txbuf 发送数据数组 */
/* 返回值; 0x10 达到最大重发次数,发送失败*/
/* 0x20 成功发送完成 */
/* 0xff 发送失败 */
/**********************************************/
BYTE NRF24L01_TxPacket(BYTE *txbuf)
{
BYTE state;
NRF_CE=0;//CE拉低,使能24L01配置
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节
NRF_CE=1;//CE置高,使能发送
while(NRF_IRQ==1);//等待发送完成
state=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
if(state&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(state&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//发送失败
}
/********************************************/
/* 函数功能:检测24L01是否存在 */
/* 返回值; 0 存在 */
/* 1 不存在 */
/********************************************/
BYTE NRF24L01_Check(void)
{
BYTE check_in_buf[5]= {0x11,0x22,0x33,0x44,0x55};
BYTE check_out_buf[5]= {0x00};
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
if((check_out_buf[0] == 0x11)&&\
(check_out_buf[1] == 0x22)&&\
(check_out_buf[2] == 0x33)&&\
(check_out_buf[3] == 0x44)&&\
(check_out_buf[4] == 0x55))return 0;
else return 1;
}
void NRF24L01_TX_Mode(void)
{
NRF_CE=0;
//NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
//NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(BYTE*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(BYTE*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通道为125
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0F); //7db增益,250kbps
//NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 (两边的速率一定要一样!!!!)
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0E); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断
NRF_CE=1; //CE置高
}
void NRF24L01_RX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(BYTE*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //设置RF通信频率
NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
delay_ms(150);
NRF_CE = 1; //CE为高,进入接收模式
}
总结
本文主要通过对STC单片机的SPI进行初始化配置,实现NRF24L01的通信,大家有兴趣的可以参考下。第一次在发文,难免有错误或不合适之处,请大家包涵。