SPI-NRF24L01

news2025/5/20 10:29:56

模块介绍

NRF24L01是NORDIC公司生产的一款无线通信芯片,采用FSK调制,内部集成NORDIC自己的Enhanced Short Burst 协议,可以实现点对点或者1对6 的无线通信,通信速率最高可以达到2Mbps. NRF24L01采用SPI通信。

①MOSI 主器件数据输出,从器件数据输入

②MISO 主器件数据输入,从器件数据输出

③SCK 时钟信号,主器件产生

④CSN 从器件使能信号

⑤CE 使能器件的发送模式或接收模式

⑥IRQ 中断信号,发生中断变低电平。TxFIFO发完并且收到ACK、RxFIFO收到数据、 达到最大重发次数

工作模式

NRF24L01工作模式,由CE和CONFIG寄存器的PWR_UP和PRIM_RX位共同控制

主要指令

配置寄存器

状态寄存器

接收模式:

Rx模式初始化过程: 初始化步骤24L01相关寄存器

①写Rx节点的地址RX_ADDR_P0

②使能AUTO ACK   EN_AA

③使能PIPE 0  (通道0)  EN_RXADDR

④选择通信频率 RF_CH

⑤选择通道0 有效数据宽度 RX_Pw_P0

⑥配置发射参数(低噪放大器增益、发射功率、无线速率)RF_SETUP

⑦配置24L01 的基本参数以及切换工作模式 CONFIG

发送模式:

Tx模式初始化过程:

①写Tx节点的地址TX_ADDR

②写RX节点的地址(主要是为了使能Auto Ack) RX_ADDR_P0

③使能AUT0    ACK  EN_AA

④使能PIPE 0  EN_RXADDR

⑤配置自动重发次数 SETUP_RETR

⑥选择通信频率  RF_CH

⑦配置发射参数(低噪放大器增益,发射功率,无限速率) RF_SETUP

⑧选择通道0 有效数据宽度 RX_Pw_P0

⑨配置24L01 的基本参数以及切换工作模式  CONFIG

下面用无线模块给串口发送数据:

移植驱动程序:

NRF24L01.c

#include "NRF24L01.h"
#include "stm32f10x.h"
#include "spi.h"

u8 tx_buf[33]="不是哥们,你吴彦祖啊";
u8 rx_buf[33]={0};

const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //·¢Ë͵ØÖ·
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};

//³õʼ»¯24L01µÄIO¿Ú
void NRF24L01_Init(void)
{ 	
	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;			   

	//ʹÄÜPB,F,D¶Ë¿ÚʱÖÓ  //PF8-CE  PF9-CSN  PD3-IRQ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 
    	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;	//PG13ÉÏÀ­ ·ÀÖ¹EN25XµÄ¸ÉÈÅ
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //ÍÆÍìÊä³ö
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);	//³õʼ»¯Ö¸¶¨IO
	GPIO_SetBits(GPIOG,GPIO_Pin_13);//ÉÏÀ­
	
	GPIO_InitStructure.GPIO_Pin = NRF24L01_CSN|NRF24L01_CE;	//PF8 9 ÍÆÍì 	  
 	GPIO_Init(NRF24L01_Port, &GPIO_InitStructure);//³õʼ»¯Ö¸¶¨IO
  GPIO_ResetBits(NRF24L01_Port,NRF24L01_CSN|NRF24L01_CE);//PF6,7,8ÏÂÀ­

	GPIO_InitStructure.GPIO_Pin  = NRF24L01_IRQ;   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PD3 ÊäÈë  
	GPIO_Init(NRF24L01_Port, &GPIO_InitStructure);
	GPIO_ResetBits(NRF24L01_Port,NRF24L01_IRQ);//PD3ÏÂÀ­
						 		 
  SPI2_Init();    		//³õʼ»¯SPI	 
	SPI_Cmd(SPI2, DISABLE); // SPIÍâÉ費ʹÄÜ

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //SPIÉèÖÃΪ˫ÏßË«Ïòȫ˫¹¤
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//SPIÖ÷»ú
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//·¢ËͽÓÊÕ8λ֡½á¹¹
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		//ʱÖÓÐü¿ÕµÍ
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	//Êý¾Ý²¶»ñÓÚµÚ1¸öʱÖÓÑØ
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSSÐźÅÓÉÈí¼þ¿ØÖÆ
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;		//¶¨Òå²¨ÌØÂÊÔ¤·ÖƵµÄÖµ:²¨ÌØÂÊÔ¤·ÖƵֵΪ16
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//Êý¾Ý´«Êä´ÓMSBλ¿ªÊ¼
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRCÖµ¼ÆËãµÄ¶àÏîʽ
	SPI_Init(SPI2, &SPI_InitStructure);  //¸ù¾ÝSPI_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèSPIx¼Ä´æÆ÷
	SPI_Cmd(SPI2, ENABLE); //ʹÄÜSPIÍâÉè
			 
	NRF24L01_CE_L; 			//ʹÄÜ24L01
	NRF24L01_CSN_H;			//SPIƬѡȡÏû  	 		 	 
}

//¼ì²â24L01ÊÇ·ñ´æÔÚ
//·µ»ØÖµ:0£¬³É¹¦;1£¬Ê§°Ü	
u8 NRF24L01_Check(void)
{
	u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
	u8 i;
	SPI2_SetSpeed(SPI_BaudRatePrescaler_4); //spiËÙ¶ÈΪ9Mhz£¨24L01µÄ×î´óSPIʱÖÓΪ10Mhz£©   	 
	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//дÈë5¸ö×ֽڵĵØÖ·.	
	NRF24L01_Read_Buf(TX_ADDR,buf,5); //¶Á³öдÈëµÄµØÖ· 
	
	for(i=0;i<5;i++)if(buf[i]!=0XA5)break;	
	
	if(i!=5)return 1;//¼ì²â24L01´íÎó	
	return 0;		 //¼ì²âµ½24L01
}

//SPIд¼Ä´æÆ÷
//reg:Ö¸¶¨¼Ä´æÆ÷µØÖ·
//value:дÈëµÄÖµ
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
	  u8 status;	
   	NRF24L01_CSN_L;                 //ʹÄÜSPI´«Êä
  	status =SPI2_ReadWriteByte(reg);//·¢ËͼĴæÆ÷ºÅ 
  	SPI2_ReadWriteByte(value);      //дÈë¼Ä´æÆ÷µÄÖµ
  	NRF24L01_CSN_H;                 //½ûÖ¹SPI´«Êä	   
  	return(status);       			//·µ»Ø×´Ì¬Öµ
}

//¶ÁÈ¡SPI¼Ä´æÆ÷Öµ
//reg:Òª¶ÁµÄ¼Ä´æÆ÷
u8 NRF24L01_Read_Reg(u8 reg)
{
	u8 reg_val;	    
 	NRF24L01_CSN_L;          //ʹÄÜSPI´«Êä		
  	SPI2_ReadWriteByte(reg);   //·¢ËͼĴæÆ÷ºÅ
  	reg_val=SPI2_ReadWriteByte(0XFF);//¶ÁÈ¡¼Ä´æÆ÷ÄÚÈÝ
  	NRF24L01_CSN_H;          //½ûÖ¹SPI´«Êä		    
  	return(reg_val);           //·µ»Ø×´Ì¬Öµ
}	

//ÔÚÖ¸¶¨Î»ÖöÁ³öÖ¸¶¨³¤¶ÈµÄÊý¾Ý
//reg:¼Ä´æÆ÷(λÖÃ)
//*pBuf:Êý¾ÝÖ¸Õë
//len:Êý¾Ý³¤¶È
//·µ»ØÖµ,´Ë´Î¶Áµ½µÄ״̬¼Ä´æÆ÷Öµ 
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
	u8 status,u8_ctr;	       
  	NRF24L01_CSN_L;           //ʹÄÜSPI´«Êä
  	status=SPI2_ReadWriteByte(reg);//·¢ËͼĴæÆ÷Öµ(λÖÃ),²¢¶Áȡ״ֵ̬   	   
 	for(u8_ctr=0;u8_ctr<len;u8_ctr++)
		pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//¶Á³öÊý¾Ý
  NRF24L01_CSN_H;       //¹Ø±ÕSPI´«Êä
  return status;        //·µ»Ø¶Áµ½µÄ״ֵ̬
}

//ÔÚÖ¸¶¨Î»ÖÃдָ¶¨³¤¶ÈµÄÊý¾Ý
//reg:¼Ä´æÆ÷(λÖÃ)
//*pBuf:Êý¾ÝÖ¸Õë
//len:Êý¾Ý³¤¶È
//·µ»ØÖµ,´Ë´Î¶Áµ½µÄ״̬¼Ä´æÆ÷Öµ
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
	u8 status,u8_ctr;	    
 	NRF24L01_CSN_L;          //ʹÄÜSPI´«Êä
  	status = SPI2_ReadWriteByte(reg);//·¢ËͼĴæÆ÷Öµ(λÖÃ),²¢¶Áȡ״ֵ̬
  	for(u8_ctr=0; u8_ctr<len; u8_ctr++)
			SPI2_ReadWriteByte(*pBuf++); //дÈëÊý¾Ý	 
  	NRF24L01_CSN_H;       //¹Ø±ÕSPI´«Êä
  	return status;          //·µ»Ø¶Áµ½µÄ״ֵ̬
}				

//Æô¶¯NRF24L01·¢ËÍÒ»´ÎÊý¾Ý
//txbuf:´ý·¢ËÍÊý¾ÝÊ×µØÖ·
//·µ»ØÖµ:·¢ËÍÍê³É×´¿ö
u8 NRF24L01_TxPacket(u8 *txbuf)
{
	u8 sta;
 	SPI2_SetSpeed(SPI_BaudRatePrescaler_4);//spiËÙ¶ÈΪ9Mhz£¨24L01µÄ×î´óSPIʱÖÓΪ10Mhz£©   
	NRF24L01_CE_L;
  NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//дÊý¾Ýµ½TX BUF  32¸ö×Ö½Ú
 	NRF24L01_CE_H;//Æô¶¯·¢ËÍ	   
	while(GPIO_ReadOutputDataBit(NRF24L01_Port,NRF24L01_IRQ)!=0);//µÈ´ý·¢ËÍÍê³É
	sta = NRF24L01_Read_Reg(STATUS);  //¶Áȡ״̬¼Ä´æÆ÷µÄÖµ	   
	NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖ¾
	if(sta&MAX_TX)//´ïµ½×î´óÖØ·¢´ÎÊý
	{
		NRF24L01_Write_Reg(FLUSH_TX,0xff);//Çå³ýTX FIFO¼Ä´æÆ÷ 
		return MAX_TX; 
	}
	if(sta&TX_OK)//·¢ËÍÍê³É
	{
		return TX_OK;
	}
	return 0xff;//ÆäËûÔ­Òò·¢ËÍʧ°Ü
}

//Æô¶¯NRF24L01·¢ËÍÒ»´ÎÊý¾Ý
//txbuf:´ý·¢ËÍÊý¾ÝÊ×µØÖ·
//·µ»ØÖµ:0£¬½ÓÊÕÍê³É£»ÆäËû£¬´íÎó´úÂë
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
	u8 sta;		    							   
	SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spiËÙ¶ÈΪ9Mhz£¨24L01µÄ×î´óSPIʱÖÓΪ10Mhz£©   
	sta=NRF24L01_Read_Reg(STATUS);  //¶Áȡ״̬¼Ä´æÆ÷µÄÖµ    	 
	NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //Çå³ýTX_DS»òMAX_RTÖжϱêÖ¾
	if(sta&RX_OK)//½ÓÊÕµ½Êý¾Ý
	{
		NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//¶ÁÈ¡Êý¾Ý
		NRF24L01_Write_Reg(FLUSH_RX,0xff);//Çå³ýRX FIFO¼Ä´æÆ÷ 
		return 0; 
	}	   
	return 1;//ûÊÕµ½ÈκÎÊý¾Ý
}		

//¸Ãº¯Êý³õʼ»¯NRF24L01µ½RXģʽ
//ÉèÖÃRXµØÖ·,дRXÊý¾Ý¿í¶È,Ñ¡ÔñRFƵµÀ,²¨ÌØÂʺÍLNA HCURR
//µ±CE±ä¸ßºó,¼´½øÈëRXģʽ,²¢¿ÉÒÔ½ÓÊÕÊý¾ÝÁË		   
void NRF24L01_RX_Mode(void)
{
		NRF24L01_CE_L;	  
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//дRX½ÚµãµØÖ·
	  
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);    //ʹÄÜͨµÀ0µÄ×Ô¶¯Ó¦´ð    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//ʹÄÜͨµÀ0µÄ½ÓÊÕµØÖ·  	 
  	NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);	     //ÉèÖÃRFͨÐÅÆµÂÊ		  
  	NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//Ñ¡ÔñͨµÀ0µÄÓÐЧÊý¾Ý¿í¶È 	    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒæ¿ªÆô   
  	NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//ÅäÖûù±¾¹¤×÷ģʽµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕģʽ 
  	NRF24L01_CE_H; //CEΪ¸ß,½øÈë½ÓÊÕģʽ 
}					

//¸Ãº¯Êý³õʼ»¯NRF24L01µ½TXģʽ
//ÉèÖÃTXµØÖ·,дTXÊý¾Ý¿í¶È,ÉèÖÃRX×Ô¶¯Ó¦´ðµÄµØÖ·,Ìî³äTX·¢ËÍÊý¾Ý,Ñ¡ÔñRFƵµÀ,²¨ÌØÂʺÍLNA HCURR
//PWR_UP,CRCʹÄÜ
//µ±CE±ä¸ßºó,¼´½øÈëRXģʽ,²¢¿ÉÒÔ½ÓÊÕÊý¾ÝÁË		   
//CEΪ¸ß´óÓÚ10us,ÔòÆô¶¯·¢ËÍ.	 
void NRF24L01_TX_Mode(void)
{														 
		NRF24L01_CE_L;	    
  	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//дTX½ÚµãµØÖ· 
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //ÉèÖÃTX½ÚµãµØÖ·,Ö÷ҪΪÁËʹÄÜACK	  

  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //ʹÄÜͨµÀ0µÄ×Ô¶¯Ó¦´ð    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //ʹÄÜͨµÀ0µÄ½ÓÊÕµØÖ·  
  	NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//ÉèÖÃ×Ô¶¯ÖØ·¢¼ä¸ôʱ¼ä:500us + 86us;×î´ó×Ô¶¯ÖØ·¢´ÎÊý:10´Î
  	NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //ÉèÖÃRFͨµÀΪ40
  	NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //ÉèÖÃTX·¢Éä²ÎÊý,0dbÔöÒæ,2Mbps,µÍÔëÉùÔöÒæ¿ªÆô   
  	NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //ÅäÖûù±¾¹¤×÷ģʽµÄ²ÎÊý;PWR_UP,EN_CRC,16BIT_CRC,½ÓÊÕģʽ,¿ªÆôËùÓÐÖжÏ
		NRF24L01_CE_H;//CEΪ¸ß,10usºóÆô¶¯·¢ËÍ
}




NRF24L01.h

#ifndef _nrf24l01_H
#define _nrf24l01_H

#include "SPI.h"
#include "stm32f10x.h"
#include "usart.h"

//24L01²Ù×÷Ïß Ò»¹²8¸ùÏߣ¬ÆäÖÐÁ½¸ùµçÔ´Ïß ÒÔÏÂΪÆäÓàÁù¸ùÏß×öÈçÏ·â×°
#define NRF24L01_Port GPIOB
#define NRF24L01_CE   GPIO_Pin_8 //24L01ƬѡÐźÅ
#define NRF24L01_CSN  GPIO_Pin_9 //SPIƬѡÐźÅ	   
#define NRF24L01_IRQ  GPIO_Pin_6  //IRQÖ÷»úÊý¾ÝÊäÈë
     //ĬÈÏÈý¸ùÏ߸úSPIÓ²¼þÓйØ

#define NRF24L01_CSN_L   GPIO_ResetBits(NRF24L01_Port,NRF24L01_CSN)
#define NRF24L01_CSN_H   GPIO_SetBits(NRF24L01_Port,NRF24L01_CSN)
#define NRF24L01_CE_L   GPIO_ResetBits(NRF24L01_Port,NRF24L01_CE)
#define NRF24L01_CE_H   GPIO_SetBits(NRF24L01_Port,NRF24L01_CE)
#define NRF24L01_IRQ_L   GPIO_ResetBits(NRF24L01_Port,NRF24L01_IRQ)
#define NRF24L01_IRQ_H   GPIO_SetBits(NRF24L01_Port,NRF24L01_IRQ)
//24L01·¢ËͽÓÊÕÊý¾Ý¿í¶È¶¨Òå
#define TX_ADR_WIDTH    5   	//5×ֽڵĵØÖ·¿í¶È
#define RX_ADR_WIDTH    5   	//5×ֽڵĵØÖ·¿í¶È
#define TX_PLOAD_WIDTH  32  	//32×Ö½ÚµÄÓû§Êý¾Ý¿í¶È
#define RX_PLOAD_WIDTH  32  	//32×Ö½ÚµÄÓû§Êý¾Ý¿í¶È


							   	   
//NRF24L01¼Ä´æÆ÷²Ù×÷ÃüÁî
#define NRF_READ_REG    0x00  //¶ÁÅäÖüĴæÆ÷,µÍ5λΪ¼Ä´æÆ÷µØÖ·
#define NRF_WRITE_REG   0x20  //дÅäÖüĴæÆ÷,µÍ5λΪ¼Ä´æÆ÷µØÖ·
#define RD_RX_PLOAD     0x61  //¶ÁRXÓÐЧÊý¾Ý,1~32×Ö½Ú
#define WR_TX_PLOAD     0xA0  //дTXÓÐЧÊý¾Ý,1~32×Ö½Ú
#define FLUSH_TX        0xE1  //Çå³ýTX FIFO¼Ä´æÆ÷.·¢ÉäģʽÏÂÓÃ
#define FLUSH_RX        0xE2  //Çå³ýRX FIFO¼Ä´æÆ÷.½ÓÊÕģʽÏÂÓÃ
#define REUSE_TX_PL     0xE3  //ÖØÐÂʹÓÃÉÏÒ»°üÊý¾Ý,CEΪ¸ß,Êý¾Ý°ü±»²»¶Ï·¢ËÍ.
#define NOP             0xFF  //¿Õ²Ù×÷,¿ÉÒÔÓÃÀ´¶Á״̬¼Ä´æÆ÷	 
//SPI(NRF24L01)¼Ä´æÆ÷µØÖ·
#define CONFIG          0x00  //ÅäÖüĴæÆ÷µØÖ·;bit0:1½ÓÊÕģʽ,0·¢Éäģʽ;bit1:µçÑ¡Ôñ;bit2:CRCģʽ;bit3:CRCʹÄÜ;
                              //bit4:ÖжÏMAX_RT(´ïµ½×î´óÖØ·¢´ÎÊýÖжÏ)ʹÄÜ;bit5:ÖжÏTX_DSʹÄÜ;bit6:ÖжÏRX_DRʹÄÜ
#define EN_AA           0x01  //ʹÄÜ×Ô¶¯Ó¦´ð¹¦ÄÜ  bit0~5,¶ÔӦͨµÀ0~5
#define EN_RXADDR       0x02  //½ÓÊÕµØÖ·ÔÊÐí,bit0~5,¶ÔӦͨµÀ0~5
#define SETUP_AW        0x03  //ÉèÖõØÖ·¿í¶È(ËùÓÐÊý¾ÝͨµÀ):bit1,0:00,3×Ö½Ú;01,4×Ö½Ú;02,5×Ö½Ú;
#define SETUP_RETR      0x04  //½¨Á¢×Ô¶¯ÖØ·¢;bit3:0,×Ô¶¯ÖØ·¢¼ÆÊýÆ÷;bit7:4,×Ô¶¯ÖØ·¢ÑÓʱ 250*x+86us
#define RF_CH           0x05  //RFͨµÀ,bit6:0,¹¤×÷ͨµÀƵÂÊ;
#define RF_SETUP        0x06  //RF¼Ä´æÆ÷;bit3:´«ÊäËÙÂÊ(0:1Mbps,1:2Mbps);bit2:1,·¢É书ÂÊ;bit0:µÍÔëÉù·Å´óÆ÷ÔöÒæ
#define STATUS          0x07  //״̬¼Ä´æÆ÷;bit0:TX FIFOÂú±êÖ¾;bit3:1,½ÓÊÕÊý¾ÝͨµÀºÅ(×î´ó:6);bit4,´ïµ½×î¶à´ÎÖØ·¢
                              //bit5:Êý¾Ý·¢ËÍÍê³ÉÖжÏ;bit6:½ÓÊÕÊý¾ÝÖжÏ;
#define MAX_TX  		0x10  //´ïµ½×î´ó·¢ËÍ´ÎÊýÖжÏ
#define TX_OK   		0x20  //TX·¢ËÍÍê³ÉÖжÏ
#define RX_OK   		0x40  //½ÓÊÕµ½Êý¾ÝÖжÏ

#define OBSERVE_TX      0x08  //·¢Ëͼì²â¼Ä´æÆ÷,bit7:4,Êý¾Ý°ü¶ªÊ§¼ÆÊýÆ÷;bit3:0,ÖØ·¢¼ÆÊýÆ÷
#define CD              0x09  //ÔØ²¨¼ì²â¼Ä´æÆ÷,bit0,ÔØ²¨¼ì²â;
#define RX_ADDR_P0      0x0A  //Êý¾ÝͨµÀ0½ÓÊÕµØÖ·,×î´ó³¤¶È5¸ö×Ö½Ú,µÍ×Ö½ÚÔÚǰ
#define RX_ADDR_P1      0x0B  //Êý¾ÝͨµÀ1½ÓÊÕµØÖ·,×î´ó³¤¶È5¸ö×Ö½Ú,µÍ×Ö½ÚÔÚǰ
#define RX_ADDR_P2      0x0C  //Êý¾ÝͨµÀ2½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P3      0x0D  //Êý¾ÝͨµÀ3½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P4      0x0E  //Êý¾ÝͨµÀ4½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define RX_ADDR_P5      0x0F  //Êý¾ÝͨµÀ5½ÓÊÕµØÖ·,×îµÍ×Ö½Ú¿ÉÉèÖÃ,¸ß×Ö½Ú,±ØÐëͬRX_ADDR_P1[39:8]ÏàµÈ;
#define TX_ADDR         0x10  //·¢Ë͵ØÖ·(µÍ×Ö½ÚÔÚǰ),ShockBurstTMģʽÏÂ,RX_ADDR_P0Óë´ËµØÖ·ÏàµÈ
#define RX_PW_P0        0x11  //½ÓÊÕÊý¾ÝͨµÀ0ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P1        0x12  //½ÓÊÕÊý¾ÝͨµÀ1ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P2        0x13  //½ÓÊÕÊý¾ÝͨµÀ2ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P3        0x14  //½ÓÊÕÊý¾ÝͨµÀ3ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P4        0x15  //½ÓÊÕÊý¾ÝͨµÀ4ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define RX_PW_P5        0x16  //½ÓÊÕÊý¾ÝͨµÀ5ÓÐЧÊý¾Ý¿í¶È(1~32×Ö½Ú),ÉèÖÃΪ0Ôò·Ç·¨
#define NRF_FIFO_STATUS 0x17  //FIFO״̬¼Ä´æÆ÷;bit0,RX FIFO¼Ä´æÆ÷¿Õ±êÖ¾;bit1,RX FIFOÂú±êÖ¾;bit2,3,±£Áô
                              //bit4,TX FIFO¿Õ±êÖ¾;bit5,TX FIFOÂú±êÖ¾;bit6,1,Ñ­»··¢ËÍÉÏÒ»Êý¾Ý°ü.0,²»Ñ­»·;
//
void NRF24L01_Init(void);						//³õʼ»¯
void NRF24L01_RX_Mode(void);					//ÅäÖÃΪ½ÓÊÕģʽ
void NRF24L01_TX_Mode(void);					//ÅäÖÃΪ·¢ËÍģʽ
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//дÊý¾ÝÇø
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);	//¶ÁÊý¾ÝÇø		  
u8 NRF24L01_Read_Reg(u8 reg);					//¶Á¼Ä´æÆ÷
u8 NRF24L01_Write_Reg(u8 reg, u8 value);		//д¼Ä´æÆ÷
u8 NRF24L01_Check(void);						//¼ì²é24L01ÊÇ·ñ´æÔÚ
u8 NRF24L01_TxPacket(u8 *txbuf);				//·¢ËÍÒ»¸ö°üµÄÊý¾Ý
u8 NRF24L01_RxPacket(u8 *rxbuf);				//½ÓÊÕÒ»¸ö°üµÄÊý¾Ý


#endif

初始化串口1usart.c以及printf重定向


 
       // USART1初始化
       void  myusart_init(void)
       {
            GPIO_InitTypeDef GPIOInitStruct;
            USART_InitTypeDef USARTInitStruct;
	        NVIC_InitTypeDef NVIC_Initstruct;
	
  	        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	    
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
	
			 //A9 TX
		    GPIOInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
		    GPIOInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
		    GPIOInitStruct.GPIO_Pin = GPIO_Pin_9;
		    GPIO_Init(GPIOA,&GPIOInitStruct);
			
	       //A10 RX
	
			GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;
			GPIOInitStruct.GPIO_Pin = GPIO_Pin_10;
			GPIO_Init(GPIOA,&GPIOInitStruct);
	
	
	
			USARTInitStruct.USART_BaudRate = 115200;
			USARTInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
			USARTInitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
			USARTInitStruct.USART_Parity = USART_Parity_No;
			USARTInitStruct.USART_StopBits = USART_StopBits_1;
			USARTInitStruct.USART_WordLength = USART_WordLength_8b;
			USART_Init(USART1,&USARTInitStruct);
			USART_Cmd(USART1,ENABLE);
            USART_ITConfig(USART1,  USART_IT_RXNE,ENABLE);
			
			NVIC_Initstruct.NVIC_IRQChannel = USART1_IRQn;
			NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 0;
			NVIC_Initstruct.NVIC_IRQChannelSubPriority = 0;
			NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
			NVIC_Init(&NVIC_Initstruct);
 
          }




int fputc(int ch, FILE *p)//printfÖØ¶¨Ïò
{
   
	  
	     USART_SendData(USART1, (u8)ch);
	     while (USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);	 

	     return ch;
	

}

spi.c(这里初始化SPI2可以随意因为驱动程序里重新初始化了)

#include "stm32f10x.h"
#include "spi.h"
 
void SPI2_Init(void)
{
 
    GPIO_InitTypeDef GPIO_InitStruct;
	SPI_InitTypeDef  SPI_InitStruct;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
	
   //SPI2:SCK:PB13、MISO:PB14、MOSI:PB15
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    GPIO_SetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
	
 
    SPI_InitStruct.SPI_Direction =SPI_Direction_2Lines_FullDuplex;//SPI设置为双线双向全双工
	SPI_InitStruct.SPI_Mode = SPI_Mode_Master;    //设置为主模式
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;//设置SPI数据大小为8位
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;      //设置SPI默认时钟悬空为高电平
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;     //设置SPI数据捕获在第二个时钟沿
	SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;        //设置SPI NSS引脚由软件管理
	SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//设置波特率预分频值为256
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;//设置SPI模式为从高位传输
	SPI_InitStruct.SPI_CRCPolynomial = 7;//设置SPI_CRC值计算的多项式
    SPI_Init(SPI2,&SPI_InitStruct);
    SPI_Cmd(SPI2, ENABLE );  //使能SPI2外设                                                                                                                       
}
//SPI2读写一个字节
u8 SPI2_ReadWriteByte(u8 dat)
{
   u8 t;
   while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) == RESET)//等待发送缓存器为空
	{
	    t++;
		if(t>=200)
		{	
		 return 0;//超时返回错误标志
		}
	  	
	
	}
	 SPI_I2S_SendData(SPI2,dat);
	while( SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//等待接收
  {
	   t++;
		if(t>=200)
		{
		  return 0;//超时返回错误标志
		}
	  	
	}
  return  SPI_I2S_ReceiveData(SPI2);
	
}
//设置SPI波特率
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler )
{
  SPI_Cmd(SPI2,DISABLE);//修改波特率前需禁用SPI
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
  SPI2->CR1 &= 0XFFC7;//将SPI控制寄存器1(CR1)的BR[2:0]3、4、5位清零,其他位不变这三位控制波特率预分频系数
  SPI2->CR1 |= SPI_BaudRatePrescaler;//将新的预分频值写入CR1的BR位
  SPI_Cmd(SPI2, ENABLE );
 
}

spi.h

#ifndef _SPI_H_
#define _SPI_H_
#include "stm32f10x.h"

void SPI2_Init(void);
u8 SPI2_ReadWriteByte(u8 dat);
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler );



#endif

main.c



extern u8 tx_buf[33];
extern u8 rx_buf[33];

int main(void)
{

	

	myusart_init();
	NRF24L01_Init();
	while(NRF24L01_Check())	 //检测NRF24L01是否存在
	 {
		printf("Error  \n ");			
	 }
	
     NRF24L01_TX_Mode(); //TX模式

	 if(NRF24L01_TxPacket(tx_buf) == MAX_TX )//达到最大重发次数
		{
			printf(" %s \r\n",tx_buf);	//打印发送的数据
		}
	
	
	 while(1)
	{



	}
}

接线的话参考NRF24L01.h和SPI.c的标注

下面是实现结果:(按两次复位键发送一次数据)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python黑科技:无痛修改第三方库源码

需求不符合 很多时候&#xff0c;我们下载的 第三方库 是不会有需求不满足的情况&#xff0c;但也有极少的情况&#xff0c;第三方库 没有兼顾到需求&#xff0c;导致开发者无法实现相关功能。 如何通过一些操作将 第三方库 源码进行修改&#xff0c;是我们将要遇到的一个难点…

一区严选!挑战5天一篇脂质体组学 DAY1-5

Day 1! 前期已经成功挑战了很多期NHANES啦&#xff01;打算来试试孟德尔随机化领域&#xff5e; 随着孟德尔随机化研究的普及&#xff0c;现在孟德尔发文的难度越来越高&#xff0c;简单的双样本想被接收更是难上加难&#xff0c;那么如何破除这个困境&#xff0c;这次我打算…

自学-408-《计算机网络》(总结速览)

文章目录 第一章 计算机网络概述1. 计算机网络的定义2. 计算机网络的基本功能3. 计算机网络的分类4. 计算机网络的层次结构5. 计算机网络的协议6. 计算机网络的组成部分7. 计算机网络的应用8. 互联网的概念 物理层的主要功能第二章 数据链路层和局域网1. 数据链路层的功能2. 局…

【质量管理】纠正、纠正措施和预防的区别与解决问题的四重境界

“质量的定义就是符合要求”&#xff0c;我们在文章【质量管理】人们对于质量的五个错误观念-CSDN博客中提到过&#xff0c;这也是质量大师克劳士比所说的。“质量的系统就是预防”&#xff0c;防止出现产品不良而造成的质量损失。 质量问题的解决可以从微观和宏观两个方面来考…

新手SEO优化实战快速入门

内容概要 对于SEO新手而言&#xff0c;系统化掌握基础逻辑与实操路径是快速入门的关键。本指南以站内优化为切入点&#xff0c;从网站结构、URL设计到内链布局&#xff0c;逐层拆解搜索引擎友好的技术框架&#xff1b;同时聚焦关键词挖掘与内容策略&#xff0c;结合工具使用与…

sqli-labs靶场 less 11

文章目录 sqli-labs靶场less 11 POS联合注入 sqli-labs靶场 每道题都从以下模板讲解&#xff0c;并且每个步骤都有图片&#xff0c;清晰明了&#xff0c;便于复盘。 sql注入的基本步骤 注入点注入类型 字符型&#xff1a;判断闭合方式 &#xff08;‘、"、’、“”&…

tomcat部署项目打开是404?

问题描述 今天在帮助一个小伙伴解决问题的时候 部署成功了 就是打不开总是404 他这个项目是公司的一个18年的项目 巨老&#xff01;&#xff01;&#xff01; HTTP状态 404 - 未找到 类型 状态报告 描述 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示…

[Linux]解决虚拟机 ubantu系统下网络的问题

问题来源&#xff1a;打开ubantu发现网络连接标识消失 解决步骤&#xff1a; 重新安装&#xff0c;前面操作无效 切换桥接模式、直连手机网络 已解决&#xff1a;

如何使用stable diffusion 3获得最佳效果

参考&#xff1a;How to get the best results from Stable Diffusion 3 Scaling Rectified Flow Transformers for High-Resolution Image Synthesis prompting SD3 不再受限于CLIP的最长77个token的长度限制&#xff0c;可以输入更长的prompt。 &#xff08;两个CLIP模型的…

Java学习笔记1——编程基础

一、整数类型变量 注意&#xff1a;每个字符型常量占两个字节 二、自动类型转换和强制类型转换 ​​​三、算术运算符 四、赋值运算符 五、比较运算符 六、逻辑运算符 七、运算符的优先级 运算符的优先级可以通过以下口诀来记忆&#xff1a; 括号优先&#xff0c;单目次之&am…

微服务核心知识点深度解析:从组件到架构设计

微服务核心知识点深度解析&#xff1a;从组件到架构设计 微服务核心知识点深度解析&#xff1a;从组件到架构设计一、Spring Cloud 5 大核心组件详解二、服务注册与发现&#xff1a;微服务的 “通讯录”概念解析Spring Cloud 中的实现 三、Nacos&#xff1a;不止是注册中心核心…

SpringBoot3+EasyExcel通过WriteHandler动态实现表头重命名

方案简介 为了通过 EasyExcel 实现动态表头重命名&#xff0c;可以封装一个方法&#xff0c;传入动态的新表头名称列表&#xff08;List<String>&#xff09;&#xff0c;并结合 WriteHandler 接口来重命名表头。同时&#xff0c;通过 EasyExcel 将数据直接写入到输出流…

Python小练习系列 Vol.11:回文数筛选(filter + 字符串反转)

&#x1f9e0; Python小练习系列 Vol.11&#xff1a;回文数筛选&#xff08;filter 字符串反转&#xff09; &#x1f50d; 本期我们用 Python 的 filter() 函数结合字符串反转技巧&#xff0c;一行代码搞定“回文数”的判断与筛选&#xff01; &#x1f9e9; 一、题目描述 回…

BUUCTF-web刷题篇(5)

13.upload1 文件上传漏洞&#xff08;上传图片&#xff09; 按照传统方法&#xff0c;新建文件&#xff08;xinjian&#xff09;写一句话木马&#xff0c;利用Windows文件后缀识别的特点&#xff0c;将后缀名改为图片后缀名(xinjian.jpg)&#xff0c;上传文件&#xff0c;抓包…

NestJS——创建项目、编写User模块

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

《Python Web部署应知应会》No2:如何基于FastAPI 和 OLLAMA 架构实现高并发 AI 推理服务

《Python Web部署应知应会》No2&#xff1a;如何基于FastAPI 和 OLLAMA 架构实现高并发 AI 推理服务&#xff08;上&#xff09; 摘要&#xff1a; 在 FastAPI 和 OLLAMA 架构中实现高并发 AI 推理服务&#xff0c;并优化性能指标采集和缓存策略&#xff0c;可以充分利用 asy…

NUUO摄像头debugging_center_utils命令执行漏洞

免责声明&#xff1a;本号提供的网络安全信息仅供参考&#xff0c;不构成专业建议。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权&#xff0c;请及时与我联系&#xff0c;我将尽快处理并删除相关内容。 漏洞描述 NUUO NVR是中国台湾省NUUO公司旗…

2.pycharm部署Ai - 编程好助手

一、pycharm安装continue插件 1.提前安装好pycharm&#xff0c;并双击打开 2.File – Setting 3.Plugins – 搜索Continue &#xff0c; 点击Install安装 4.点ok 二、获取硅基流动API 1.登入网站&#xff1a;https://siliconflow.cn/zh-cn/#/&#xff0c;并注册登入 2.获取AP…

uniapp + Axios + 小程序封装网络请求

前言 小程序自带的网络请求使用起来比较麻烦&#xff0c;不便于管理&#xff0c;就需要封装网络请求&#xff0c;减少繁琐步骤&#xff0c;封装最终效果&#xff0c;根据类别将网络请求封装在文件中&#xff0c;使用得时候调用文件名名称加文件中得自定义名称&#xff0c;就可…

初始数据库--MySQL

一&#xff0c;数据库&#xff08;DataBase&#xff09;概述 思考程序开发中数据存储问题&#xff1f; 变量 int c 10; 对象{名字&#xff0c;价格&#xff0c;颜色} 集合类-->对象 以上方式存储数据都是在内存中存储 程序运行结束后数据都释放了 …