看了两天的24l01的相关资料了,一直有点模糊,今天下午感觉有点懂了,在板子上调试成功了,但是还没进行通讯测试。stm32和arduino进行通信还没成功 ,:(
先把stm32的NRF24L01配置的过程说一下吧(这是我跟着代码写的,有点简单,可能还有差错):
1 . 首先初始化相关的端口和SPI等;
1 void SPI2_NRF24L01_init(void) 2 { 3 SPI_InitTypeDef SPI_InitStructure; 4 GPIO_InitTypeDef GPIO_InitStructure; 5 6 /* Enable SPI2 GPIOB clocks */ 7 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE); 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); 9 /* Configure SPI2 pins: SCK, MISO and MOSI */ 10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 11 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 12 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_Out_PP; // 13 GPIO_Init(GPIOB, &GPIO_InitStructure); 14 15 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 16 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 17 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 18 GPIO_Init(GPIOC,&GPIO_InitStructure); 19 20 21 /* Configure PB.11 as Output push-pull, used as Flash Chip select */ 22 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; 23 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 24 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 25 GPIO_Init(GPIOB, &GPIO_InitStructure); 26 27 28 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //NRF24L01 MODE-CE 29 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 30 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 31 GPIO_Init(GPIOC, &GPIO_InitStructure); 32 /* Deselect the FLASH: Chip Select high */ 33 34 35 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //NRF24L01 IRQ 36 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 37 GPIO_Init(GPIOB, &GPIO_InitStructure); 38 GPIO_SetBits(GPIOB, GPIO_Pin_8); //On 39 NotSelect_SDR(); 40 41 /* SPI2 configuration */ 42 SPI_Cmd(SPI2,DISABLE); 43 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 44 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 45 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; 46 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; 47 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; 48 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; 49 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; 50 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 51 SPI_InitStructure.SPI_CRCPolynomial = 7; 52 SPI_Init(SPI2,&SPI_InitStructure); 53 54 /* Enable SPI2 */ 55 SPI_Cmd(SPI2,ENABLE); 56 }
这是我的引脚连接。
2 . 然后开始初始化 NRF模块
01 . 首先先说一下spi的读、写数据方法:
1 u8 Spi_RW(u8 dat) 2 { 3 /* 当 SPI发送缓冲器非空时等待 */ 4 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); 5 /* 通过 SPI2发送一字节数据 */ 6 SPI_I2S_SendData(SPI2, dat); 7 /* 当SPI接收缓冲器为空时等待 */ 8 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); 9 /* Return the byte read from the SPI bus */ 10 return SPI_I2S_ReceiveData(SPI2); 11 }
然后说一下模块的读、写方法:
1 uint8_t NRF_Read_Reg(uint8_t reg) 2 { 3 uint8_t reg_val; 4 SPI_CSN_L(); /* 选通器件 */ 5 Spi_RW(reg); /* 写寄存器地址 */ 6 reg_val = Spi_RW(0); /* 读取该寄存器返回数据 #define NRF_READ_REG 0x00 // 读寄存器指令 */ 7 SPI_CSN_H(); /* 禁止该器件 */ 8 return reg_val; 9 } 10 11 uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value) 12 { 13 uint8_t status; 14 SPI_CSN_L(); /* 先选通器件 */ 15 status = Spi_RW(reg); /* 写寄存器地址,同时也可以读出该寄存器 */ 16 Spi_RW(value); /* 然后就向该地址的寄存器写数据 */ 17 SPI_CSN_H(); /* 最后禁止该器件 */ 18 return status; 19 }
02 . 然后就是按照模块的寄存器说明来向相应的寄存器里写入数据来设置:
1 NRF_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //写RX节点地址 2 NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //写TX节点地址 3 NRF_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 4 NRF_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 5 NRF_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a); //设置自动重发间隔时间:500us;最大自动重发次数:10次 6 NRF_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为CHANAL 7 NRF_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
这些寄存器的地址和设置的数据在NRF24L01.h中都有宏定义:
1 //***************************************NRF24L01寄存器指令******************************************************* 2 #define NRF_READ_REG 0x00 // 读寄存器指令 3 #define NRF_WRITE_REG 0x20 // 写寄存器指令 4 #define R_RX_PL_WID 0x60 5 #define RD_RX_PLOAD 0x61 // 读取接收数据指令 6 #define WR_TX_PLOAD 0xA0 // 写待发数据指令 7 #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令 8 #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令 9 #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令 10 #define NOP 0xFF // 保留 11 //*************************************SPI(nRF24L01)寄存器地址**************************************************** 12 #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式 13 #define EN_AA 0x01 // 自动应答功能设置 14 #define EN_RXADDR 0x02 // 可用信道设置 15 #define SETUP_AW 0x03 // 收发地址宽度设置 16 #define SETUP_RETR 0x04 // 自动重发功能设置 17 #define RF_CH 0x05 // 工作频率设置 18 #define RF_SETUP 0x06 // 发射速率、功耗功能设置 19 #define NRFRegSTATUS 0x07 // 状态寄存器 20 #define OBSERVE_TX 0x08 // 发送监测功能 21 #define CD 0x09 // 地址检测 22 #define RX_ADDR_P0 0x0A // 频道0接收数据地址 23 #define RX_ADDR_P1 0x0B // 频道1接收数据地址 24 #define RX_ADDR_P2 0x0C // 频道2接收数据地址 25 #define RX_ADDR_P3 0x0D // 频道3接收数据地址 26 #define RX_ADDR_P4 0x0E // 频道4接收数据地址 27 #define RX_ADDR_P5 0x0F // 频道5接收数据地址 28 #define TX_ADDR 0x10 // 发送地址寄存器 29 #define RX_PW_P0 0x11 // 接收频道0接收数据长度 30 #define RX_PW_P1 0x12 // 接收频道1接收数据长度 31 #define RX_PW_P2 0x13 // 接收频道2接收数据长度 32 #define RX_PW_P3 0x14 // 接收频道3接收数据长度 33 #define RX_PW_P4 0x15 // 接收频道4接收数据长度 34 #define RX_PW_P5 0x16 // 接收频道5接收数据长度 35 #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置 36 //************************************************************************************** 37 //*********************************************NRF24L01************************************* 38 #define RX_DR 6 //中断标志 39 #define TX_DS 5 40 #define MAX_RT 4 41 42 #define MODEL_RX 1 //普通接收 43 #define MODEL_TX 2 //普通发送 44 #define MODEL_RX2 3 //接收模式2,用于双向传输 45 #define MODEL_TX2 4 //发送模式2,用于双向传输 46 47 #define RX_PLOAD_WIDTH 32 48 #define TX_PLOAD_WIDTH 32 49 #define TX_ADR_WIDTH 5 50 #define RX_ADR_WIDTH 5
03 . 然后就基本都设置好了,还要设置一下发送模式
1 NRF_Write_Reg(NRF_WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断开启,16位CRC,主发送 2 NRF_Write_Reg(FLUSH_TX,0xff); 3 NRF_Write_Reg(FLUSH_RX,0xff); 4 5 Spi_RW(0x50); 6 Spi_RW(0x73); 7 NRF_Write_Reg(NRF_WRITE_REG+0x1c,0x01); 8 NRF_Write_Reg(NRF_WRITE_REG+0x1d,0x07);
04 . 最后可以check一下模块和STM32是否连接成功:
1 u8 Nrf24l01_Check(void) 2 { 3 u8 buf1[5]; 4 u8 i; 5 /*写入5个字节的地址. */ 6 NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,5); 7 /*读出写入的地址 */ 8 NRF_Read_Buf(TX_ADDR,buf1,5); 9 /*比较*/ 10 for(i=0;i<5;i++) 11 { 12 if(buf1[i]!=TX_ADDRESS[i]) 13 break; 14 } 15 if(i==5) 16 return SUCCESS ; //MCU与NRF成功连接 17 else 18 return ERROR ; //MCU与NRF不正常连接 19 }
3 . NRF24L01 发送数据方式 :
先拉低CE ,然后 将数据写入 TX_FIFO ,然后拉高CE,保持10us以上,数据会无线发送出去。
4 . 其他
今天简单写了一些,晚些做完项目后再补充吧,另外网上有很多的教程和资源,我发现我一开始读的时候读不懂,后来按照示例代码走了一遍,然后再看看其他一些教程,发现更容易理解,另外一定要准备纸笔,按照
官方手册中或其他人写的教程把整个步骤画一下流程图,整理思绪,有助理解。
时间: 2024-10-26 07:18:36