OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3233|回复: 2

NRF24L01单对单传输间断收到信号的问题。

[复制链接]

2

主题

3

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2016-10-4
在线时间
4 小时
发表于 2016-10-4 21:53:22 | 显示全部楼层 |阅读模式
     我的代码是两个STM32F103C8T6最小系统使用硬件SPI1利用NRF24L01进行单向通信,采用外部中断检测IRQ。发送端和接收端自检都顺利通过,发送端的STATUS不断的返回0x1E(即最大重发),接收端的STATUS不断返回0x0E。发送端平均每发送1000-2000次接收端才有可能接收到一次。而且,一旦接收到,两边给出的相应标志位都十分正常。我想知道我那里出现错误了呢?
发送端函数
主函数和中断
[mw_shl_code=applescript,true]#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.\r\n");                       
                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:%x\r\n",Status);
                if(Status&0x10)                        //达到最大重发次数
                {
//                printf("Send Failed.\r\n");
                Led=~Led;
                }
                if(Status&0x20)                        //发送完成并返回ACK
                {
                        printf("Send Success.\r\n");
                        if(DataNum<12)
                        {DataNum++;}
                        else
                        {DataNum=0;}
                }
                if(Status&0x40)                        //接收到数据
                {
                        printf("Receive Message.\r\n");
                }
                WriteCom(FLUSH_TX,NOP);                        //清除TX_FIFO
                WriteCom(FLUSH_RX,NOP);                        //清除RX_FIFO
                WriteCom(STATUS,Status);                //清除所有标志
                EXTI_ClearITPendingBit(EXTI_Line2);
                GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
[/mw_shl_code]

NRF24L01部分C文件

[mw_shl_code=applescript,true]#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);
        //GPIO
        GPIOSPIConfig.GPIO_Mode=GPIO_Mode_IPD;
        GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6;                        //PA6主机接收                MISO
        GPIOSPIConfig.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片选                                CSN
        GPIO_Init(GPIOA,&GPIOSPIConfig);
       
        GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7|                        //PA7主机发送                MOSI
                                                                                                 GPIO_Pin_5;                        //PA5时钟线                        SCK
        GPIO_Init(GPIOA,&GPIOSPIConfig);
        //SPI
        SPI_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);
        //GPIO
        GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIOSPIConfig.GPIO_Pin=GPIO_Pin_6|                                                                                                //PA7从机发送                MISO
                                                                                                 GPIO_Pin_5;                                                                                                //PA5时钟线                        SCK
        GPIOSPIConfig.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片选                                CSN
        GPIO_Init(GPIOA,&GPIOSPIConfig);
       
        GPIOSPIConfig.GPIO_Mode=GPIO_Mode_AF_OD;
        GPIOSPIConfig.GPIO_Pin=GPIO_Pin_7;                                                                                                //PA6从机接收                MOSI
        GPIO_Init(GPIOA,&GPIOSPIConfig);
        //SPI
        SPI_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);                                                        //使能数据通道0
        WriteCom(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]=%d\r\n",Num,(int)Status[Num]);
//        }
}
void ReceiveConfig()                                                                                                                                //点对点接收配置函数
{
        CE=0;                                                                                                                                                                                //进入待机模式,开始接收指令
        WriteData(RX_ADDR_P0,AddrCode,5);                        //写入RX地址
        WriteCom(EN_AA,0x01);                                                                        //写入RX地址自动应答
        WriteCom(EN_RXADDR,0x01);                                                        //使能数据通道0
        WriteCom(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;                        //启动nrf24L01
        Status=WriteReadByte(W_REGISTER|RegAddr);
        WriteReadByte(W_REGISTER|Data);       
        CSN=1;                        //关闭nrf24L01
        return Status;
}
u8 ReadCom(u8 RegAddr,u8 Data)                                                                                        //读取函数
{
        u8 Status;
        CSN=0;                        //启动nrf24L01
        Status=WriteReadByte(R_REGISTER|RegAddr);
        WriteReadByte(R_REGISTER|Data);       
        CSN=1;                        //关闭nrf24L01
        return Status;
}
u8 WriteData(u8 RegAddr,u8* DataCode,int Width)                        //大量数据写入函数
{
        u8 Status;
        int Num;
        CSN=0;                                                                                                                                                //启动nrf24L01
        Status=WriteReadByte(W_REGISTER+RegAddr);
//        DataCode--;                                                                                                                                //指针小BUG
        for(Num=0;Num<Width;Num++)
        {
                WriteReadByte(*DataCode);                                                                //写入数组中所有数据       
//                printf("Data[%d]=%x\r\n",Num,(*DataCode));
                DataCode++;
        }
        CSN=1;                                                                                                                                                //关闭nrf24L01
        return Status;
}
u8 ReadData(u8 RegAddr,u8* DataCode,int Width)                        //大量数据读取函数
{
        u8 Status;
        int Num;
        CSN=0;                                                                                                                                                //启动nrf24L01
        Status=WriteReadByte(R_REGISTER+RegAddr);                                                                                       
        for(Num=0;Num<Width;Num++)
        {
                DataCode[Num]=WriteReadByte(NOP);                                                                //写入数组中所有数据       
                //printf("Data[%d]=%x\r\n",Num,(*DataCode));
        }
        CSN=1;                                                                                                                                                //关闭nrf24L01
        return Status;
}
/*==========应用层==========*/
char nrf24L01Check()                                                                                                                                //nrf24L01自检函数
{
        u8 DataTrySend[5]={0xA1,0XA2,0XA3,0XA4,0xA5};
        u8 DataTryRec[5]={0x00,0x00,0x00,0x00,0x00};
        int Num,Check=0;
        WriteData(TX_ADDR,DataTrySend,5);
        ReadData(TX_ADDR,DataTryRec,5);
        for(Num=0;Num<5;Num++)
        {
                if(DataTrySend[Num]==DataTryRec[Num])
                {Check++;}
        }
        if(Check==5)
        {
                printf("nrf24L01 check OK.\r\n");
                return 1;
        }
        else
        {
                printf("nrf24L01 check ERROR.\r\n");
                return 0;
        }
}
[/mw_shl_code]

NRF24L01部分H文件

[mw_shl_code=applescript,true]#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                //发送地址
#define        RX_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 CE        PAout(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
[/mw_shl_code]

接收端函数
主函数和中断
[mw_shl_code=applescript,true]#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.\r\n");               
        while(!nrf24L01Check());                        //自检                       
        ReceiveConfig();                       
        CE=1;
        while(1)
        {               
//                CE=0;
//                printf("Config Status:%x\r\n",ReadCom(STATUS,NOP));
//                delay_ms(100);
        }
}
void EXTI2_IRQHandler()
{
                u8 Status;
                Status=ReadCom(STATUS,NOP);
                printf("Config Status:%x\r\n",Status);
                if(Status&0x10)                        //达到最大重发次数
                {
                        printf("Send Failed.\r\n");
                }
                if(Status&0x20)                        //发送完成并返回ACK
                {
                        printf("Send Success.\r\n");
                }
                if(Status&0x40)                        //接收到数据
                {
                        printf("Receive Message.\r\n");
                        Led=~Led;
                        CSN=0;                        //启动nrf24L01
                        WriteReadByte(R_RX_PAYLOAD);
                        Status=WriteReadByte(NOP);       
                        CSN=1;                        //关闭nrf24L01
                        printf("Result:%c\r\n",Status);
                }
                WriteCom(FLUSH_TX,NOP);                        //清除TX_FIFO
                WriteCom(FLUSH_RX,NOP);                        //清除RX_FIFO
                WriteCom(STATUS,Status);                //清除所有标志
                EXTI_ClearITPendingBit(EXTI_Line2);
                GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
[/mw_shl_code]

NRF24L01部分和发送端一样。
外部中断是非常灵敏,完全没有问题的。



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

47

主题

212

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
292
金钱
292
注册时间
2016-1-2
在线时间
80 小时
发表于 2016-10-4 23:48:17 | 显示全部楼层
再也不想用这个模块了,一年前毕业设计,用51和24传输,从头到尾自己看资料,调试的,做完后放在那里不动,答辩前2天,用作品预演,妹的,突然之间不传数了,一步一步找问题,都没有找出来
回复 支持 反对

使用道具 举报

2

主题

3

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2016-10-4
在线时间
4 小时
 楼主| 发表于 2016-10-5 21:34:45 | 显示全部楼层
2938690046 发表于 2016-10-4 23:48
再也不想用这个模块了,一年前毕业设计,用51和24传输,从头到尾自己看资料,调试的,做完后放在那里不动, ...

模块应是没问题的,不然为什么开发板上能随插随用呢?静等大神来光顾吧。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-30 19:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表