初级会员
- 积分
- 60
- 金钱
- 60
- 注册时间
- 2013-8-23
- 在线时间
- 0 小时
|
<!--StartFragment --><div>最近用51单片机研究射频卡522,事先给空白卡里面写入学号信息,刷卡也能读取了,但是问题来了:“每次刷卡,刷一两次(可以正常读取卡信息哦)后,若显示读卡失败“ERR”时,读卡模块就卡住了,不会读取新过来的卡的数据了”<br />
需要每次单片机重新复位,才能继续读取新卡数据。<br />
以下是部分主程序部分,另外NRF2401和RC522调用函数子程序网上基本一样的,所以这里版面问题没扔出来。<br />
////////////////////////////////////////////////////<br />
//入口主函数<br />
void main( )<br />
{ <br />
unsigned char status;<br />
unsigned char t; <br />
CE=0;<br />
SCK=0;<br />
CSN=1; <br />
UartInital();<br />
InitializeSystem( ); //初始化<br />
while (1)<br />
{ <br />
status=PcdRequest( PICC_REQALL, &RevBuffer[0] ) ; <br />
if( status!= MI_OK ) //寻天线区内未进入休眠状态的卡,返回卡片类型 2字节 <br />
{ status=PcdRequest( PICC_REQIDL, &RevBuffer[0] ) ; <br />
if( status != MI_OK ){ //寻天线区内未进入休眠状态的卡,返回卡片类型 2字节 <br />
continue;<br />
} <br />
}<br />
status=PcdAnticoll( &RevBuffer[2] );<br />
if( status!= MI_OK ){ //防冲撞,返回卡的序列号 4字节 <br />
DisplayListChar(10,1,lyERR); //错误返回<br />
continue; <br />
}<br />
memcpy(MLastSelectedSnr,&RevBuffer[2],4);<br />
status=PcdSelect(MLastSelectedSnr);<br />
if(status!= MI_OK ){ //选卡<br />
DisplayListChar(10,1,lyERR);<br />
continue;<br />
}<br />
status=PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, MLastSelectedSnr);<br />
if( status!= MI_OK){ // 校验卡密码A<br />
DisplayListChar(10,1,lyERR);<br />
continue; <br />
}<br />
status=PcdRead(1,&RevBuffer[2]); <br />
if(PcdRead(1,&RevBuffer[2])!= MI_OK) // 读卡了?<br />
{ <br />
<br />
status=PcdRead(1,&RevBuffer[2]); <br />
if(status!= MI_OK)//再一次读卡确认<br />
{<br />
DisplayListChar(10,1,lyERR);<br />
continue;<br />
<br />
}<br />
}<br />
 cdHalt(); //终止卡的操作 </div>
<h2>就是以下2401部分导致刷卡刷正确一次卡死的问题所在。以下若删了,刷卡没问题(所以证明我的RFID-RC522程序没错的,问题出在下面主程序的小部分)。按说while循环里面怎么可能刷一次就卡住了呢,我猜仅仅发送了一次卡住没继续循环了,仅个人观点,大神来看看</h2>
<div><br />
<strong> DisplayListChar(0,1,&RevBuffer[2]);<br />
for( t=0;t<=strlen(&RevBuffer[2]);t++)<br />
Tx_Buf[t]=*(&RevBuffer[2]+t); </strong></div>
<div><strong> UartSend_string(Tx_Buf);<br />
<br />
if(nRF24L01_TxPacket(Tx_Buf)==TX_DS)//发送数组中的数据 或者使用这一句 nRF24L01_TxPacket(unsigned char * tx_buf)<br />
{<br />
</strong></div>
<div><strong> }</strong></div>
<div><strong> delay(200); //间隔时间<br />
<br />
}<br />
}</strong></div>
<div> </div>
<div> </div>
<div><br />
</div>
<div>那位大神帮忙看看,刷卡一两次后就要单片机复位,RC522模块才能继续读取新的卡,这是什么情况啊,起码来一个新卡,重新读吧?该怎么改好呢,跪求大神指点一二</div>
<div><br />
以下是NRF2401的部分程序:#ifndef __2401_H__<br />
#define __2401_H__</div>
<div> </div>
<div>#define uchar unsigned char<br />
#define uint unsigned int<br />
//定义的端口为模块上标的端口//<br />
sbit MISO=P3^4;<br />
sbit MOSI=P3^0;<br />
sbit IRQ=P3^3;<br />
sbit CE=P3^5;<br />
sbit CSN=P3^1;<br />
sbit SCK=P3^2;<br />
uchar bdata sta; //状态标志bdata就是可位寻址内部数据存储区<br />
sbit RX_DR = sta ^6;//接收数据准备就绪<br />
sbit TX_DS =sta^5;//已发送数据<br />
sbit MAX_RT =sta^4;<br />
#define TX_ADR_WIDTH 5 // 5 uints TX address width<br />
#define RX_ADR_WIDTH 5 // 5 uints RX address width<br />
#define TX_PLOAD_WIDTH 10 // 32 uints TX payload<br />
#define RX_PLOAD_WIDTH 10 // 32 uints TX payload</div>
<div> </div>
<div><br />
uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址<br />
uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址<br />
uchar idata Tx_Buf[TX_PLOAD_WIDTH]={0};//发送数据</div>
<div>#define READ_REG 0x00 // 读寄存器指令<br />
#define WRITE_REG 0x20 // 写寄存器指令<br />
#define RD_RX_PLOAD 0x61 // 读取接收数据指令<br />
#define WR_TX_PLOAD 0xA0 // 写待发数据指令<br />
#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令<br />
#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令<br />
#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令<br />
#define NOP 0xFF // 保留<br />
//**********************************SPI(nRF24L01)寄存器地址**/<br />
#define CONFIG 0x00 // 配置收发状态,CRC校验模式<br />
//以及收发状态响应方式<br />
#define EN_AA 0x01 // 自动应答功能设置<br />
#define EN_RXADDR 0x02 // 可用信道设置<br />
#define SETUP_AW 0x03 // 收发地址宽度设置<br />
#define SETUP_RETR 0x04 // 自动重发功能设置<br />
#define RF_CH 0x05 // 工作频率设置<br />
#define RF_SETUP 0x06 // 发射速率、功耗功能设置<br />
#define STATUS 0x07 // 状态寄存器<br />
#define OBSERVE_TX 0x08 // 发送监测功能<br />
#define CD 0x09 // 地址检测 <br />
#define RX_ADDR_P0 0x0A // 频道0接收数据地址<br />
#define RX_ADDR_P1 0x0B // 频道1接收数据地址<br />
#define RX_ADDR_P2 0x0C // 频道2接收数据地址<br />
#define RX_ADDR_P3 0x0D // 频道3接收数据地址<br />
#define RX_ADDR_P4 0x0E // 频道4接收数据地址<br />
#define RX_ADDR_P5 0x0F // 频道5接收数据地址<br />
#define TX_ADDR 0x10 // 发送地址寄存器<br />
#define RX_PW_P0 0x11 // 接收频道0接收数据长度<br />
#define RX_PW_P1 0x12 // 接收频道0接收数据长度<br />
#define RX_PW_P2 0x13 // 接收频道0接收数据长度<br />
#define RX_PW_P3 0x14 // 接收频道0接收数据长度<br />
#define RX_PW_P4 0x15 // 接收频道0接收数据长度<br />
#define RX_PW_P5 0x16 // 接收频道0接收数据长度<br />
#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置</div>
<div>//******************************************延时函数<br />
//长延时<br />
void Deelay(unsigned int s) //延时约1ms,当s=1时;<br />
{<br />
unsigned int i,j; <br />
for(i=0;i<1000;i++)for(j=0;j<s;j++);<br />
}<br />
//短延时<br />
void deelay_ms(unsigned int x) //延时约0.1ms,当x=1时<br />
{<br />
unsigned int i,j;<br />
i=0;<br />
for(i=0;i<x;i++)<br />
{<br />
j=108;;<br />
while(j--);<br />
}<br />
}</div>
<div>//****IO口模拟SPI总线代码********/<br />
uchar SPI_RW(uchar byte)//这一段程序看懂了,觉得写得挺好<br />
{<br />
uchar bit_ctr;<br />
for(bit_ctr=0;bit_ctr<8;bit_ctr++)<br />
{<br />
MOSI=(byte&0x80);<br />
<br />
byte=(byte<<1);<br />
SCK=1;<br />
byte|=MISO;<br />
SCK=0;<br />
}<br />
return(byte);<br />
}<br />
uchar SPI_RW_Reg (uchar reg,uchar value) // 向寄存器REG写一个字节,同时返回状态字节<br />
{<br />
uchar status;<br />
CSN=0;<br />
status=SPI_RW(reg);<br />
SPI_RW(value);<br />
CSN=1;<br />
return(status);<br />
}<br />
uchar SPI_Read (uchar reg )//读取寄存器值的函数<br />
{<br />
uchar reg_val;<br />
CSN=0;<br />
SPI_RW(reg);<br />
reg_val=SPI_RW(0);<br />
CSN=1;<br />
return(reg_val);<br />
}<br />
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)//发射缓冲区访问函数<br />
{<br />
uchar status,byte_ctr;<br />
CSN = 0; // Set CSN low, init SPI tranaction<br />
status = SPI_RW(reg); // Select register to write to and read status byte<br />
for(byte_ctr=0; byte_ctr<bytes; byte_ctr++) // then write all byte in buffer(*pBuf)<br />
SPI_RW(*pBuf++);<br />
CSN = 1; // Set CSN high again<br />
return(status); // return nRF24L01 status byte<br />
}<br />
//******************发送模式代码*************/<br />
/*void TX_Mode(void)<br />
{<br />
CE=0;<br />
SPI_RW_Reg(FLUSH_TX,0x00);<br />
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01<br />
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack<br />
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ackipe0<br />
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // Enable Pipe0<br />
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...1a<br />
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40 //不一样零:: 通道选择0<br />
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:1Mbps, LNA:HCURR<br />
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //不一样零:没这一句 设置接收数据长度,本次设置为32字<br />
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);<br />
CE=1;<br />
delay_ms(100);<br />
}<br />
void Transmit(unsigned char * tx_buf)<br />
{<br />
CE=0; //StandBy I模式 <br />
<br />
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 发射//缓冲区访问函数 装载接收端地址<br />
SPI_RW_Reg(FLUSH_TX,0x00); //不一样二:这一句多了 寄存器访问函数<br />
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据 <br />
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送<br />
CE=1; //置高CE,激发数据发送<br />
delay_ms(150);<br />
} */<br />
unsigned char nRF24L01_TxPacket(unsigned char * tx_buf)<br />
{<br />
CE=0;<br />
<br />
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // <br />
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); <br />
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); <br />
<br />
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // <br />
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // <br />
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); //<br />
SPI_RW_Reg(WRITE_REG + RF_CH, 0); // <br />
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // <br />
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // <br />
CE=1;<br />
// deelay_ms(150);<br />
//while(IRQ!=0);</div>
<div> sta=SPI_Read(READ_REG + STATUS); // read register STATUS's value<br />
SPI_RW_Reg(WRITE_REG+STATUS,sta); // clear interrupt flag(TX_DS)<br />
if(sta&MAX_RT)<br />
{ SPI_RW_Reg(FLUSH_TX,0xff); <br />
//Deelay(10);<br />
return MAX_RT; <br />
}<br />
if(sta&TX_DS)<br />
return TX_DS; <br />
return 0xff; </div>
<div> <br />
</div>
<div><br />
}</div>
<div><br />
#endif <br />
<br />
<br />
<div>那位大神帮忙看看,刷卡一两次后就要单片机复位,RC522模块才能继续读取新的卡,这是什么情况啊,起码来一个新卡,重新读吧?该怎么改好呢,跪求大神指点一二</div>
<div><br />
<br />
</div>
</div> |
|