news 2026/5/20 5:12:59

SPI_NRF24L01

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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-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的标注

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 5:10:20

如何利用ChatGPT定制指令打造专业创意写作伙伴:完整指南

如何利用ChatGPT定制指令打造专业创意写作伙伴&#xff1a;完整指南 ChatGPT定制指令是提升AI写作辅助能力的终极工具&#xff0c;通过精心设计的系统提示&#xff0c;你可以将ChatGPT转变为专业的创意写作伙伴。本文将详细介绍如何利用ChatGPT_Custom_Instructions项目中的资…

作者头像 李华
网站建设 2026/5/20 5:08:08

Go语言配置中心:Apollo与Nacos

Go语言配置中心&#xff1a;Apollo与Nacos 1. Nacos客户端 import "github.com/nacos-group/nacos-sdk-go/clients"client, err : clients.NewConfigClient(map[string]interface{}{"serverAddresses": []string{"http://localhost:8848"}, })2.…

作者头像 李华
网站建设 2026/5/20 5:06:43

DocQuery最佳实践:企业文档自动化处理的10个技巧

DocQuery最佳实践&#xff1a;企业文档自动化处理的10个技巧 【免费下载链接】docquery An easy way to extract information from documents 项目地址: https://gitcode.com/gh_mirrors/do/docquery DocQuery是一款强大的文档信息提取工具&#xff0c;能轻松分析半结构…

作者头像 李华