STC单片机硬件SPI驱动NRF24L01

最近用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的通信,大家有兴趣的可以参考下。第一次在发文,难免有错误或不合适之处,请大家包涵。

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STC51单片机是一种常用的8位单片机,而nRF24L01是一款常用的无线通信模块。下面是对STC51单片机nRF24L01进行无线通信测试的步骤: 1.连接硬件:首先,将STC51单片机nRF24L01模块通过SPI接口连接起来。确保连接正确且稳定。 2.编写代码:使用STC51单片机的开发工具,编写适当的代码,以初始化nRF24L01模块并进行通信设置。代码应包括设置nRF24L01的传输频率、数据速率、功率等参数,以及接收和发送数据的相关函数。 3.设置发送端:在代码中,将STC51单片机作为发送端。设置发送的数据和数据的发送方式。可以选择以固定的时间间隔发送数据,或通过外部输入信号触发发送。 4.设置接收端:同样在代码中设置STC51单片机作为接收端。设置接收模式,并实现接收数据的函数。确保接收到的数据能够准确地解析和处理。 5.编译和烧录:将编写的代码进行编译,并通过编程器将生成的HEX文件烧录到STC51单片机中。 6.测试:将发送端和接收端分别与电源连接,确保它们之间的通信正常。可以通过串口调试助手等工具来观察发送和接收的数据。 7.改进和优化:如果通信中遇到问题,可以根据实际情况进行调试和优化。例如,通过调整数据传输速率、增加冗余校验等方式来提高通信质量。 总之,进行STC51单片机nRF24L01无线通信测试需要连接硬件、编写代码、设置发送和接收端,并进行测试和优化。通过这些步骤,可以实现基于STC51单片机nRF24L01的无线通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值