天线|RF射频
直播中

侯倩

7年用户 204经验值
私信 关注
[问答]

NRF24L01单对单传输间断收到信号问题的解决办法?

     我的代码是两个STM32F103C8T6最小系统使用硬件SPI1利用NRF24L01进行单向通信,采用外部中断检测IRQ。发送端和接收端自检都顺利通过,发送端的STATUS不断的返回0x1E(即最大重发),接收端的STATUS不断返回0x0E。发送端平均每发送1000-2000次接收端才有可能接收到一次。而且,一旦接收到,两边给出的相应标志位都十分正常。我想知道我那里出现错误了呢?
发送端函数
主函数和中断
[AppleScript] 纯文本查看 复制代码
#include "stm32f10x.h"#include "delay.h"#include "sys.h"#include "usart.h"#include "nrf24L01.h"#include "EXti.h"#include "Led.h"u8 Data[]={'A','B','C','D'};int DataNum=0;int main(void){delay_init();uart_init(115200);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SPIInitMaster();//主机初始化函数EXTIInit();LedInit();printf("Init down.rn");while(!nrf24L01Check());//自检SendConfig();//发送配置函数while(1){CE=0;WriteCom(W_TX_PAYLOAD,Data[DataNum]);CE=1;delay_ms(10);}}void EXTI2_IRQHandler(){u8 Status;Status=ReadCom(STATUS,NOP);//printf("Config Status:%xrn",Status);if(Status&0x10)//达到最大重发次数{//printf("Send Failed.rn");Led=~Led;}if(Status&0x20)//发送完成并返回ACK{printf("Send Success.rn");if(DataNum<12){DataNum++;}else{DataNum=0;}}if(Status&0x40)//接收到数据{printf("Receive Message.rn");}WriteCom(FLUSH_TX,NOP);//清除TX_FIFOWriteCom(FLUSH_RX,NOP);//清除RX_FIFOWriteCom(STATUS,Status);//清除所有标志EXTI_ClearITPendingBit(EXTI_Line2);GPIO_SetBits(GPIOA,GPIO_Pin_2);}
NRF24L01部分C文件
[AppleScript] 纯文本查看 复制代码
#include "nrf24L01.h"#include "delay.h"#include "usart.h"//地址编码u8 AddrCode[]={0xA1,0xA2,0xA3,0xA4,0xA5};//结构体定义GPIO_InitTypeDef GPIOSPIConfig;SPI_InitTypeDef SPIConfig;/*==========初始化层==========*/void SPIInitMaster()//主机初始化函数{/*主机模式*//*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO PA7_SPI1_MOSI PA3_CE*///时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO| RCC_APB2Periph_SPI1,ENABLE);//GPIOGPIOSPIConfig.GPIO_Mode=GPIO_Mode_IPD;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6;//PA6主机接收MISOGPIOSPIConfig.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIOSPIConfig);GPIOSPIConfig.GPIO_Mode=GPIO_Mode_Out_PP;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_3|//PA3模式选择CE GPIO_Pin_4;//PA4片选CSNGPIO_Init(GPIOA,&GPIOSPIConfig);GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7|//PA7主机发送MOSI GPIO_Pin_5;//PA5时钟线SCKGPIO_Init(GPIOA,&GPIOSPIConfig);//SPISPI_I2S_DeInit(SPI1);//SPI复位SPIConfig.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//全双工SPIConfig.SPI_Mode=SPI_Mode_Master;//主机SPIConfig.SPI_DataSize=SPI_DataSize_8b;//8位字长SPIConfig.SPI_CPOL=SPI_CPOL_Low;//低电平空闲SPIConfig.SPI_CPHA=SPI_CPHA_1Edge;//第一个边沿开始采集SPIConfig.SPI_NSS=SPI_NSS_Soft;//软件片选SPIConfig.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//8分频SPIConfig.SPI_FirstBit=SPI_FirstBit_MSB;//高位在前(单数据发送)SPIConfig.SPI_CRCPolynomial=7;//校验值多项式SPI_Init(SPI1,&SPIConfig);//SPI使能SPI_Cmd(SPI1,ENABLE);CSN=1;}void SPIInitSlave()//从机初始化函数{/*从机模式*//*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO PA7_SPI1_MOSI PA3_CE*///时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO| RCC_APB2Periph_SPI1,ENABLE);//GPIOGPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6|//PA7从机发送MISO GPIO_Pin_5;//PA5时钟线SCKGPIOSPIConfig.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIOSPIConfig);GPIOSPIConfig.GPIO_Mode=GPIO_Mode_Out_PP;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_3|//PA3模式选择CE GPIO_Pin_4;//PA4片选CSNGPIO_Init(GPIOA,&GPIOSPIConfig);GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_OD;GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7;//PA6从机接收MOSIGPIO_Init(GPIOA,&GPIOSPIConfig);//SPISPI_I2S_DeInit(SPI1);//SPI复位SPIConfig.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//全双工SPIConfig.SPI_Mode=SPI_Mode_Slave;//从机SPIConfig.SPI_DataSize=SPI_DataSize_8b;//8位字长SPIConfig.SPI_CPOL=SPI_CPOL_Low;//低电平空闲SPIConfig.SPI_CPHA=SPI_CPHA_1Edge;//第一个边沿开始采集SPIConfig.SPI_NSS=SPI_NSS_Soft;//软件片选SPIConfig.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//8分频SPIConfig.SPI_FirstBit=SPI_FirstBit_MSB;//高位在前(单数据发送)SPIConfig.SPI_CRCPolynomial=7;//校验值多项式SPI_Init(SPI1,&SPIConfig);//SPI使能SPI_Cmd(SPI1,ENABLE);CSN=1;}void SendConfig()//点对点发送配置函数{//u8 Status[8];//int Num;CE=0;//进入待机模式,开始接收指令//Status[0]=WriteCom(TX_ADDR,AddrCode[0]);//写入TX地址//Status[1]=WriteCom(RX_ADDR_P0,5);//选择通道,默认5字节宽度//Status[2]=WriteCom(EN_AA,0x01);//使能自动应答//Status[3]=WriteCom(EN_RXADDR,AddrCode[0]);//写入RX地址//Status[4]=WriteCom(SETUP_RETR,0xff);//最大延时,最多重发//Status[5]=WriteCom(RF_CH,40);//选择通信频率//Status[6]=WriteCom(RF_SETUP,0x0f);//射频配置,0db增益,2Mbps,低噪声增益开启 //Status[7]=WriteCom(CONFIG,0x0e);//发送模式WriteData(TX_ADDR,AddrCode,5);//写入TX地址WriteData(RX_ADDR_P0,AddrCode,5);//写入RX地址WriteCom(EN_AA,0x01);//写入RX地址自动应答WriteCom(EN_RXADDR,0x01);//使能数据通道0WriteCom(SETUP_RETR,0x0f);//最小延时,最多重发WriteCom(RF_CH,Channel1);//选择通信频率WriteCom(RF_SETUP,0x0f);//射频配置,0db增益,2Mbps,低噪声增益开启 WriteCom(CONFIG,0x0e);//发送模式CE=1;//for(Num=0;Num<8;Num++)//{//printf("Status[%d]=%drn",Num,(int)Status[Num]);//}}void ReceiveConfig()//点对点接收配置函数{CE=0;//进入待机模式,开始接收指令WriteData(RX_ADDR_P0,AddrCode,5);//写入RX地址WriteCom(EN_AA,0x01);//写入RX地址自动应答WriteCom(EN_RXADDR,0x01);//使能数据通道0WriteCom(RF_CH,Channel1);//选择通信频率WriteCom(RX_PW_P0,32);//设置数据宽度WriteCom(RF_SETUP,0x0f);//射频配置,0db增益,2Mbps,低噪声增益开启 WriteCom(CONFIG,0x0f);//发送模式CE=1;}/*==========数据传输底层==========*/u8 WriteReadByte(u8 TxData)//收发一字节函数{u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位{retry++;if(retry>200)return 0;}  SPI_I2S_SendData(SPI1, TxData);  //SPI1发送一个数据retry=0;while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位{retry++;if(retry>200)return 0;}      return SPI_I2S_ReceiveData(SPI1);  //返回SPI1最近接收的数据    }/*==========数据传输层===========*/u8 WriteCom(u8 RegAddr,u8 Data)//写入函数{u8 Status;CSN=0;//启动nrf24L01Status=WriteReadByte(W_REGISTER|RegAddr);WriteReadByte(W_REGISTER|Data);CSN=1;//关闭nrf24L01return Status;}u8 ReadCom(u8 RegAddr,u8 Data)//读取函数{u8 Status;CSN=0;//启动nrf24L01Status=WriteReadByte(R_REGISTER|RegAddr);WriteReadByte(R_REGISTER|Data);CSN=1;//关闭nrf24L01return Status;}u8 WriteData(u8 RegAddr,u8* DataCode,int Width)//大量数据写入函数{u8 Status;int Num;CSN=0;//启动nrf24L01Status=WriteReadByte(W_REGISTER+RegAddr);//DataCode--;//指针小BUGfor(Num=0;Num NRF24L01部分H文件
[AppleScript] 纯文本查看 复制代码
#ifndef _NRF24L01_H_#define _NRF24L01_H_#include "sys.h"/*PA4_SPI1_NSS PA5_SPI1_SCK PA6_SPI1_MISO PA7_SPI1_MOSI PA3_CE*//*操作指令*/#define R_REGISTER  0x00//读操作前缀#define W_REGISTER  0x20//写操作前缀#define R_RX_PAYLOAD  0x61//读数据指令#define W_TX_PAYLOAD 0xA0//写数据指令#define FLUSH_TX 0xE1//清空发送数据#define FLUSH_RX 0xE2//清空接收数据#define NOP 0xFF//空操作,读状态寄存器/*寄存器地址*/#define CONFIG  0x00//基本配置寄存器#define EN_AA  0x01//自动应答使能寄存器#define EN_RXADDR  0x02//接收地址使能寄存器#define SETUP_RETR 0x04//自动重发寄存器#define RF_CH 0x05//射频频率设置寄存器#define RF_SETUP 0x06//射频配置寄存器#define STATUS 0x07//状态寄存器#define RX_ADDR_P0 0x0A//通道0接收地址#define TX_ADDR  0x10//发送地址#defineRX_PW_P0 0x11//通道0数据宽度/*通信频道*/#define Channel1 40#define Channel2 41#define Channel3 42#define Channel4 43#define Channel5 44#define Channel6 45/*使能引脚映射*/#define IRQ PAin(2)#define CEPAout(3)#define CSN PAout(4)/*==========初始化层==========*/void SPIInitMaster(void);//主机初始化函数void SPIInitSlave(void);//从机初始化函数void SendConfig(void);//点对点发送配置函数void ReceiveConfig(void);//点对点接收配置函数/*==========数据传输底层==========*/u8 WriteReadByte(u8 Data);//收发一字节函数/*==========数据传输层===========*/u8 WriteCom(u8 RegAddr,u8 Data);//写入命令函数u8 ReadCom(u8 RegAddr,u8 Data);//读取函数u8 WriteData(u8 RegAddr,u8* DataCode,int Width);//大量数据写入函数u8 ReadData(u8 RegAddr,u8* DataCode,int Width);//大量数据读取函数/*==========应用层==========*/char nrf24L01Check(void);//nrf24L01自检函数#endif
接收端函数
主函数和中断
[AppleScript] 纯文本查看 复制代码
#include "stm32f10x.h"#include "delay.h"#include "sys.h"#include "usart.h"#include "nrf24L01.h"#include "EXTI.h"#include "Led.h"u8 Data[33];int main(void){delay_init();uart_init(115200);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SPIInitMaster();//主机初始化函数EXTIInit();LedInit();printf("Init down.rn");while(!nrf24L01Check());//自检ReceiveConfig();CE=1;while(1){//CE=0;//printf("Config Status:%xrn",ReadCom(STATUS,NOP));//delay_ms(100);}}void EXTI2_IRQHandler(){u8 Status;Status=ReadCom(STATUS,NOP);printf("Config Status:%xrn",Status);if(Status&0x10)//达到最大重发次数{printf("Send Failed.rn");}if(Status&0x20)//发送完成并返回ACK{printf("Send Success.rn");}if(Status&0x40)//接收到数据{printf("Receive Message.rn");Led=~Led;CSN=0;//启动nrf24L01WriteReadByte(R_RX_PAYLOAD);Status=WriteReadByte(NOP);CSN=1;//关闭nrf24L01printf("Result:%crn",Status);}WriteCom(FLUSH_TX,NOP);//清除TX_FIFOWriteCom(FLUSH_RX,NOP);//清除RX_FIFOWriteCom(STATUS,Status);//清除所有标志EXTI_ClearITPendingBit(EXTI_Line2);GPIO_SetBits(GPIOA,GPIO_Pin_2);}
NRF24L01部分和发送端一样。
外部中断是非常灵敏,完全没有问题的。

回帖(2)

史晓明

2020-7-22 08:15:55
再也不想用这个模块了,一年前毕业设计,用51和24传输,从头到尾自己看资料,调试的,做完后放在那里不动,答辩前2天,用作品预演,妹的,突然之间不传数了,一步一步找问题,都没有找出来
举报

陈逸群

2020-7-22 08:29:16
模块应是没问题的,不然为什么开发板上能随插随用呢?静等大神来光顾吧。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分