天线|RF射频
直播中

徐铭潞

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

NRF24L01读卡失败的解决办法?

最近用51单片机研究射频卡522,事先给空白卡里面写入学号信息,刷卡也能读取了,但是问题来了:“每次刷卡,刷一两次(可以正常读取卡信息哦)后,若显示读卡失败“ERR”时,读卡模块就卡住了,不会读取新过来的卡的数据了”

需要每次单片机重新复位,才能继续读取新卡数据。

以下是部分主程序部分,另外NRF2401和RC522调用函数子程序网上基本一样的,所以这里版面问题没扔出来。

////////////////////////////////////////////////////

//入口主函数

void main( )

{   

  unsigned char status;

  unsigned char t;

   CE=0;

    SCK=0;

    CSN=1;

   Uartinital();

    InitializeSystem( ); //初始化

    while (1)

    {  

status=PcdRequest( PICC_REQALL, &RevBuffer[0] ) ;

  if( status!= MI_OK ) //寻天线区内未进入休眠状态的卡,返回卡片类型 2字节

   {   status=PcdRequest( PICC_REQIDL, &RevBuffer[0] ) ;

       if( status != MI_OK ){ //寻天线区内未进入休眠状态的卡,返回卡片类型 2字节

  continue;

  }

   }

  status=PcdAnticoll( &RevBuffer[2] );

if(  status!= MI_OK ){  //防冲撞,返回卡的序列号 4字节

  DisplayListChar(10,1,lyERR); //错误返回

continue;

}

memcpy(MLastSelectedSnr,&RevBuffer[2],4);

status=PcdSelect(MLastSelectedSnr);

if(status!= MI_OK ){ //选卡

  DisplayListChar(10,1,lyERR);

  continue;

}

status=PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, MLastSelectedSnr);

if( status!= MI_OK){ // 校验卡密码A

  DisplayListChar(10,1,lyERR);

  continue;  

}

status=PcdRead(1,&RevBuffer[2]);                                      

if(PcdRead(1,&RevBuffer[2])!= MI_OK) // 读卡了?

{



status=PcdRead(1,&RevBuffer[2]);  

   if(status!= MI_OK)//再一次读卡确认

    {

  DisplayListChar(10,1,lyERR);

    continue;

   

    }

}

cdHalt(); //终止卡的操作

就是以下2401部分导致刷卡刷正确一次卡死的问题所在。以下若删了,刷卡没问题(所以证明我的RFID-RC522程序没错的,问题出在下面主程序的小部分)。按说while循环里面怎么可能刷一次就卡住了呢,我猜仅仅发送了一次卡住没继续循环了,仅个人观点,大神来看看




DisplayListChar(0,1,&RevBuffer[2]);

for( t=0;t<=strlen(&RevBuffer[2]);t++)

       Tx_Buf[t]=*(&RevBuffer[2]+t);

      UartSend_string(Tx_Buf);



       if(nRF24L01_TxPacket(Tx_Buf)==TX_DS)//发送数组中的数据  或者使用这一句 nRF24L01_TxPacket(unsigned char * tx_buf)

    {

   

    }

  delay(200); //间隔时间

  

  }

}






那位大神帮忙看看,刷卡一两次后就要单片机复位,RC522模块才能继续读取新的卡,这是什么情况啊,起码来一个新卡,重新读吧?该怎么改好呢,跪求大神指点一二



以下是NRF2401的部分程序:#ifndef __2401_H__

#define __2401_H__


#define uchar unsigned char

#define uint unsigned int

//定义的端口为模块上标的端口//

***it MISO=P3^4;

***it MOSI=P3^0;

***it IRQ=P3^3;

***it CE=P3^5;

***it CSN=P3^1;

***it SCK=P3^2;

uchar  bdata sta;   //状态标志bdata就是可位寻址内部数据存储区

***it RX_DR = sta ^6;//接收数据准备就绪

***it TX_DS =sta^5;//已发送数据

***it MAX_RT =sta^4;

#define TX_ADR_WIDTH    5    // 5 uints TX address width

#define RX_ADR_WIDTH    5    // 5 uints RX address width

#define TX_PLOAD_WIDTH  10   // 32 uints TX payload

#define RX_PLOAD_WIDTH  10  // 32 uints TX payload




uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址

uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址

uchar idata Tx_Buf[TX_PLOAD_WIDTH]={0};//发送数据

#define READ_REG        0x00   // 读寄存器指令

#define WRITE_REG       0x20  // 写寄存器指令

#define RD_RX_PLOAD     0x61   // 读取接收数据指令

#define WR_TX_PLOAD     0xA0   // 写待发数据指令

#define FLUSH_TX        0xE1  // 冲洗发送 FIFO指令

#define FLUSH_RX        0xE2   // 冲洗接收 FIFO指令

#define REUSE_TX_PL     0xE3   // 定义重复装载数据指令

#define NOP             0xFF   // 保留

//**********************************SPI(nRF24L01)寄存器地址**/

#define CONFIG          0x00  // 配置收发状态,CRC校验模式

//以及收发状态响应方式

#define EN_AA           0x01  // 自动应答功能设置

#define EN_RXADDR       0x02  // 可用信道设置

#define SETUP_AW        0x03  // 收发地址宽度设置

#define SETUP_RETR      0x04  // 自动重发功能设置

#define RF_CH           0x05  // 工作频率设置

#define RF_SETUP        0x06  // 发射速率、功耗功能设置

#define STATUS          0x07  // 状态寄存器

#define OBSERVE_TX      0x08  // 发送监测功能

#define CD              0x09  // 地址检测           

#define RX_ADDR_P0      0x0A  // 频道0接收数据地址

#define RX_ADDR_P1      0x0B  // 频道1接收数据地址

#define RX_ADDR_P2      0x0C  // 频道2接收数据地址

#define RX_ADDR_P3      0x0D  // 频道3接收数据地址

#define RX_ADDR_P4      0x0E  // 频道4接收数据地址

#define RX_ADDR_P5      0x0F  // 频道5接收数据地址

#define TX_ADDR         0x10  // 发送地址寄存器

#define RX_PW_P0        0x11  // 接收频道0接收数据长度

#define RX_PW_P1        0x12  // 接收频道0接收数据长度

#define RX_PW_P2        0x13  // 接收频道0接收数据长度

#define RX_PW_P3        0x14  // 接收频道0接收数据长度

#define RX_PW_P4        0x15  // 接收频道0接收数据长度

#define RX_PW_P5        0x16  // 接收频道0接收数据长度

#define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置

//******************************************延时函数

//长延时

void Deelay(unsigned int s) //延时约1ms,当s=1时;

{

unsigned int i,j;   

for(i=0;i<1000;i++)for(j=0;j
}

//短延时

void deelay_ms(unsigned int x)  //延时约0.1ms,当x=1时

{

    unsigned int i,j;

    i=0;

    for(i=0;i
    {

       j=108;;

       while(j--);

    }

}

//****IO口模拟SPI总线代码********/

uchar SPI_RW(uchar byte)//这一段程序看懂了,觉得写得挺好

{

uchar bit_ctr;

for(bit_ctr=0;bit_ctr<8;bit_ctr++)

{

   MOSI=(byte&0x80);

   

   byte=(byte<<1);

   SCK=1;

   byte|=MISO;

   SCK=0;

}

return(byte);

}

uchar SPI_RW_Reg  (uchar  reg,uchar value) // 向寄存器REG写一个字节,同时返回状态字节

{

    uchar status;

  CSN=0;

  status=SPI_RW(reg);

    SPI_RW(value);

  CSN=1;

  return(status);

}

uchar SPI_Read (uchar  reg )//读取寄存器值的函数

{

    uchar reg_val;

  CSN=0;

  SPI_RW(reg);

   reg_val=SPI_RW(0);

  CSN=1;

  return(reg_val);

}

uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)//发射缓冲区访问函数

{

uchar status,byte_ctr;

   CSN = 0;                   // Set CSN low, init SPI tranaction

   status = SPI_RW(reg);    // Select register to write to and read status byte

   for(byte_ctr=0; byte_ctr
    SPI_RW(*pBuf++);

   CSN = 1;                 // Set CSN high again

   return(status);          // return nRF24L01 status byte

}

//******************发送模式代码*************/

/*void TX_Mode(void)

{

CE=0;

SPI_RW_Reg(FLUSH_TX,0x00);

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // Writes TX_Address to nRF24L01

   SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      // Enable Auto.Ackipe0

   SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0

   SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1a

   SPI_RW_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40 //不一样零:: 通道选择0

   SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);   // TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR

SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //不一样零:没这一句 设置接收数据长度,本次设置为32字

   SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);

CE=1;

delay_ms(100);

}

void Transmit(unsigned char * tx_buf)

{

CE=0;   //StandBy I模式



SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 发射//缓冲区访问函数  装载接收端地址

SPI_RW_Reg(FLUSH_TX,0x00);  //不一样二:这一句多了 寄存器访问函数

SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);   // 装载数据

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);   // IRQ收发完成中断响应,16位CRC,主发送

CE=1;   //置高CE,激发数据发送

delay_ms(150);

} */

unsigned char  nRF24L01_TxPacket(unsigned char * tx_buf)

{

CE=0;



SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    //

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);

SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);



SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      //

SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //

SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); //

SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);   //

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);     //

CE=1;

// deelay_ms(150);

//while(IRQ!=0);

     sta=SPI_Read(READ_REG +  STATUS); // read register STATUS's value

SPI_RW_Reg(WRITE_REG+STATUS,sta); // clear interrupt flag(TX_DS)

  if(sta&MAX_RT)

   {     SPI_RW_Reg(FLUSH_TX,0xff);     

        //Deelay(10);

  return  MAX_RT;   

    }

    if(sta&TX_DS)

     return TX_DS;   

    return 0xff;     

      

      



}



#endif





那位大神帮忙看看,刷卡一两次后就要单片机复位,RC522模块才能继续读取新的卡,这是什么情况啊,起码来一个新卡,重新读吧?该怎么改好呢,跪求大神指点一二






回帖(4)

王萍

2020-4-28 09:42:54
哎。。。等了一两天了都没个人答。。。伤心中。。。
举报

陈可

2020-4-28 09:47:54
反复验证,我的刷卡程序是正确的,NRF24L01发送小部分程序----还是这一小部分的问题,单个发送接收,这程序没错,但是把这小部分2401的扔进去,就使得刷卡刷一次就死掉不执行了,需要单片机复位
举报

于扬

2020-4-28 10:06:16
共用1个SPI么?
举报

张玉

2020-4-28 10:20:27
查出来了,是串口通信和2401端口共用时冲突了
举报

更多回帖

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