当前位置: 首页 > article >正文

SPI-NRF24L01

模块介绍

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-IRQRCC_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);	//³õʼ»¯Ö¸¶¨IOGPIO_SetBits(GPIOG,GPIO_Pin_13);//ÉÏÀ­GPIO_InitStructure.GPIO_Pin = NRF24L01_CSN|NRF24L01_CE;	//PF8 9 ÍÆÍì 	  GPIO_Init(NRF24L01_Port, &GPIO_InitStructure);//³õʼ»¯Ö¸¶¨IOGPIO_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;		//¶¨Òå²¨ÌØÂÊÔ¤·ÖƵµÄÖµ:²¨ÌØÂÊÔ¤·ÖƵֵΪ16SPI_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; 			//ʹÄÜ24L01NRF24L01_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ͨµÀΪ40NRF24L01_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 TXGPIOInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIOInitStruct.GPIO_Speed = GPIO_Speed_10MHz;GPIOInitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_Init(GPIOA,&GPIOInitStruct);//A10 RXGPIOInitStruct.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:PB15GPIO_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;//设置波特率预分频值为256SPI_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);//修改波特率前需禁用SPIassert_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的标注

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

相关文章:

SPI-NRF24L01

模块介绍 NRF24L01是NORDIC公司生产的一款无线通信芯片&#xff0c;采用FSK调制&#xff0c;内部集成NORDIC自己的Enhanced Short Burst 协议&#xff0c;可以实现点对点或者1对6 的无线通信,通信速率最高可以达到2Mbps. NRF24L01采用SPI通信。 ①MOSI 主器件数据输出&#xf…...

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

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

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

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

【JavaScript】合体期功法——DOM(二)

目录 DOM事件监听案例关闭广告随机点名 事件监听版本事件类型 DOM 事件监听 事件&#xff1a;编程时系统内发生的动作或事情&#xff0c;例如用户在网页上单击一个按钮 事件监听&#xff1a;让程序检测是否产生事件&#xff0c;一旦事件触发&#xff0c;立即调用函数做出响应…...

23种设计模式中的中介者模式

定义了一个中介对象来封装一系列对象之间的交互。中介者使各对象直接不再显示地相互引用&#xff0c;从而使其松散耦合&#xff0c;且可以独立地改变它们之间的交互。 通过引入一个中介者对象&#xff0c;来协调和封装多个对象之间的交互&#xff0c;从而降低他们之间的耦合度。…...

量子计算:开启未来计算的新纪元

一、引言 在当今数字化时代&#xff0c;计算技术的飞速发展深刻地改变了我们的生活和工作方式。从传统的电子计算机到如今的高性能超级计算机&#xff0c;人类在计算能力上取得了巨大的进步。然而&#xff0c;随着科技的不断推进&#xff0c;我们面临着越来越多的复杂问题&…...

Docker 的实质作用是什么

Docker 的实质作用是什么 目录 Docker 的实质作用是什么**1. Docker 的实质作用****2. 为什么使用 Docker?****(1)解决环境一致性问题****(2)提升资源利用率****(3)简化部署与扩展****(4)加速开发与协作****3. 举例说明****总结**Docker 的实质是容器化平台,核心作用…...

Assembly语言的装饰器

Assembly语言的装饰器&#xff1a;灵活高效的代码复用 引言 在软件开发中&#xff0c;代码复用和模块化是两个至关重要的概念。它们不仅使得代码的维护变得更为简单&#xff0c;而且能极大提升开发效率。在高级语言中&#xff0c;装饰器是一种非常受欢迎的设计模式&#xff0…...

VITA 模型解读,实时交互式多模态大模型的 pioneering 之作

写在前面:实时交互llm 今天回顾一下多模态模型VITA,当时的背景是OpenAI 的 GPT-4o 惊艳亮相,然而,当我们将目光投向开源社区时,却发现能与之匹敌的模型寥寥无几。当时开源多模态大模型(MLLM),大多在以下一个或多个方面存在局限: 模态支持不全:大多聚焦于文本和图像,…...

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

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

AF3 FeaturePipeline类解读

AlphaFold3 feature_pipeline 模块 FeaturePipeline 类是一个封装类,通过调用函数np_example_to_features 实现整个数据处理流程。 源代码: def np_to_tensor_dict(np_example: Mapping[str, np.ndarray],features: Sequence[str], ) -> TensorDict:"""C…...

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

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

Java面试黄金宝典24

1. 什么是跳表 定义 跳表&#xff08;Skip List&#xff09;是一种随机化的数据结构&#xff0c;它基于有序链表发展而来&#xff0c;通过在每个节点中维护多个指向其他节点的指针&#xff0c;以多层链表的形式组织数据。其核心思想是在链表基础上增加额外层次&#xff0c;每…...

Windows 11系统下Kafka的详细安装与启动指南(JDK 1.8)

1. 安装前准备 在Windows 11系统中安装Kafka之前,需要确保满足以下条件: 1.1 系统要求 Windows 11操作系统(64位)至少4GB内存(建议8GB或更高)至少5GB可用磁盘空间管理员权限1.2 所需工具 浏览器(用于下载软件)解压工具(如7-Zip、WinRAR,Windows 11自带的解压功能也…...

树莓派超全系列文档--(16)无需交互使用raspi-config工具其三

无需交互使用raspi-config工具其三 无需交互的 raspi-configAdvanced optionsExpand filesystemNetwork interface namesNetwork proxy settingsBoot orderBootloader versionWaylandAudio config Update 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文…...

【蓝桥杯】算法笔记1

1.暴力枚举 给定一个正整数n,请找出所有满足a + b = n的整数对(a, b),其中a和b都是正整数,且a ≤ b。 输入格式:一个正整数n (1 ≤ n ≤ 10⁶) 输出格式:所有符合条件的(a, b)对,每行一对,按a的升序排列。如果没有符合条件的对,输出"No solution"。 问题分…...

爱因斯坦求和 torch

目录 向量点积 矩阵乘法 矩阵转置 向量转换相机坐标系 在 Python 的科学计算库&#xff08;如 NumPy&#xff09;中&#xff0c;einsum 是一个强大的函数&#xff0c;它可以简洁地表示各种张量运算。下面是几个不同类型的使用示例&#xff1a; 向量点积 向量点积是两个向量…...

Linux命令-sed指令

sed命令参数&#xff1a; 基本参数 -n&#xff1a;抑制默认输出&#xff0c;只显示匹配的行。 -e&#xff1a;指定 sed 脚本。 -i&#xff1a;直接修改文件内容。 -f&#xff1a;指定包含 sed 脚本的文件。 -r&#xff1a;启用扩展正则表达式。 常用操作 s&#xff1a;替换字符…...

新手SEO优化实战快速入门

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

如何使不同的窗体控件,适应不同分辨率的屏幕?

问题 当屏幕分辨率提高或降低时&#xff0c;原分辨率显示正常的控件&#xff0c;将变得很小或很大&#xff0c;字体也变得太大或太小。 解决办法 当分辨率变化时&#xff0c;采用递归的方法&#xff0c;对所有的控件放大或缩小。 public static void MainForm_Load(object s…...

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模型的…...

SakuraCat(2)Endpoint

Endpoint 功能概述 监听指定端口&#xff08;默认是 8080&#xff09;的客户端连接。接受客户端连接后&#xff0c;为每个连接创建一个新的线程进行处理。使用 Processor 类来处理客户端的请求和响应。 package com.SakuraCat.connector.protocolHandler;import com.SakuraC…...

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;抓包…...