最近用51
单片机研究射频卡522,事先给空白卡里面写入学号信息,刷卡也能读取了,但是问题来了:“每次刷卡,刷一两次(可以正常读取卡信息哦)后,若显示读卡失败“ERR”时,读卡模块就卡住了,不会读取新过来的卡的数据了”
需要每次单片机重新复位,才能继续读取新卡数据。
以下是部分主程序部分,另外NRF2401和RC522调用函数子程序网上基本一样的,所以这里版面问题没扔出来。
////////////////////////////////////////////////////
//入口主函数
void main( )
{
unsigned char status;
unsigned char t;
CE=0;
SCK=0;
CSN=1;
Uar
tinital();
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模块才能继续读取新的卡,这是什么情况啊,起码来一个新卡,重新读吧?该怎么改好呢,跪求大神指点一二