微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > 新人小白求教,89C51对RC522进行操作,无法休眠mifire S50卡,就是操作卡后无法休眠。

新人小白求教,89C51对RC522进行操作,无法休眠mifire S50卡,就是操作卡后无法休眠。

时间:10-02 整理:3721RD 点击:
extern void SendData(unsigned char dat);
extern void SendString(char *s);
extern unsigned char data RC522_Buffer[20];
#define MAXRLEN 18

unsigned char code DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char data MLastSelectedSnr[4];
unsigned char data ucComMF522Buf[MAXRLEN];

unsigned char SPI_LOOP(unsigned char Dat)
{
unsigned char data i;
ACC = Dat;
i = 8;
SPI_LOOP:
CY = ACC & 0x80;
RC522_MOSI = CY;
RC522_SCLK = 1;
CY = RC522_MISO;
RC522_SCLK = 0;
i--;
if(i)goto SPI_LOOP;
CY = ACC & 0x80;
return ACC;
}
/////////////////////////////////////////////////////////////////////
//功 能:读RC632寄存器
//参数说明:Address[IN]:寄存器地址
//返 回:读出的值
/////////////////////////////////////////////////////////////////////
unsigned char ReadRawRC(unsigned char Address)
{
RC522_SCLK = 0;
RC522_NSS = 0;
ACC = ((Address<<1)&0x7E)|0x80;
//
SPI_LOOP(ACC);
ACC = SPI_LOOP(0);
RC522_NSS = 1;
return ACC;
}

/////////////////////////////////////////////////////////////////////
//功 能:写RC632寄存器
//参数说明:Address[IN]:寄存器地址
// value[IN]:写入的值
/////////////////////////////////////////////////////////////////////
void WriteRawRC(unsigned char Address, unsigned char value)
{
RC522_SCLK = 0;
RC522_NSS = 0;
ACC = ((Address<<1)&0x7E); // 地址高位为0表示写,地位必须为0
//
SPI_LOOP(ACC);
SPI_LOOP(value);
RC522_NSS = 1;
RC522_SCLK = 1;
}
/////////////////////////////////////////////////////////////////////
//功 能:置RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask)
{
WriteRawRC(reg, ReadRawRC(reg) | mask); // set bit mask
}
/////////////////////////////////////////////////////////////////////
//功 能:清RC522寄存器位
//参数说明:reg[IN]:寄存器地址
// mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)
{
WriteRawRC(reg, ReadRawRC(reg) & mask); // clear bit mask
}

/////////////////////////////////////////////////////////////////////
//功 能:通过RC522和ISO14443卡通讯
//参数说明:Command[IN]:RC522命令字
// pInData[IN]:通过RC522发送到卡片的数据
// InLenByte[IN]:发送数据的字节长度
// pOutData[OUT]:接收到的卡片返回数据
// *pOutLenBit[OUT]:返回数据的位长度
///////PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen)//////////////////////////////////////////////////////////////
char PcdComMF522(unsigned char Command,
unsigned char pInData,
unsigned char InLenByte,
unsigned char pOutData,
unsigned char pOutLenBit)
{
char data status = MI_ERR;
unsigned char data irqEn = 0x00;
unsigned char data waitFor = 0x00;
unsigned char data lastBits;
volatile unsigned char data n,_i;
unsigned int data i;
unsigned short idata T0;
bit bdata command_bit;
switch (Command)
{
case PCD_AUTHENT: // 验证密钥
{
irqEn = 0x12;
waitFor = 0x10;
command_bit = 0;
break;
}
case PCD_TRANSCEIVE: // 发送并接收数据
{
irqEn = 0x77;
waitFor = 0x30;
command_bit = 1;
break;
}
default:break;
}
//
WriteRawRC(ComIEnReg,irqEn|0x80); // ComIEnReg:中断请求的使能位。验证密钥:(10010010)位7:管脚IRQ与Status1Reg的IRq反相。位4:允许空闲中断请求(IdleIRq位)传递到IRQ管脚上。位1:允许错误中断请求(ErrIRq位)传递到IRQ管脚上。
// 发送并接收数据:(11110111)除高位中断请求外,其他都能传到IRQ管脚上
ClearBitMask(ComIrqReg,0x80); // ComIrqReg的屏蔽位清零
WriteRawRC(CommandReg,PCD_IDLE); // CommandReg低4位写0000B,处于空闲模式
SetBitMask(FIFOLevelReg,0x80); // FIFOLevelReg中FlushBuffer位置1,表示缓冲区读和写指针清除,即缓冲区无数据,用来存放一下批数据,ErrReg的BufferOvfl清除
//
_i = InLenByte;
loop1:
WriteRawRC(FIFODataReg, *(unsigned char data*)pInData);
pInData ++;
_i --;
if(_i)goto loop1;
//
WriteRawRC(CommandReg, Command); // 验证密钥 or 发送并接收数据
//
if(command_bit)
{
SetBitMask(BitFramingReg,0x80); // 启动数据的发送
}
//
i = 300;
// TR0 = 1;
loop2:
n = ReadRawRC(ComIrqReg);
if( (n & 0x01) || (n & waitFor))goto loop2_end;
i --;
if(i)goto loop2;
loop2_end:

ClearBitMask(BitFramingReg,0x80); // StartSend位清零
//
if (i!=0)
{
if((ReadRawRC(ErrorReg)&0x1B)) // FIFO没有溢出、接收器启动并完成接收之后:(没冲突)、(CRC没出错)、(没有SOF错误)、(验证时接受字节数没错)
{
status = MI_ERR; // 验证错误
}
else
{
status = MI_OK;
if (n & irqEn & 0x01) // 发送并接收数据、定时器减到0
{
status = MI_NOTAGERR; // 没有找到目标错误
}
if (Command == PCD_TRANSCEIVE)
{
n = ReadRawRC(FIFOLevelReg); // 读FIFO保存的字节数
}// n = 0x02;
lastBits = ReadRawRC(ControlReg) & 0x07; // 最后一个接收的字节的有效位数(0则表示8位都有效)
//
if (lastBits)
{
*(unsigned short data*)pOutLenBit = (n-1)*8 + lastBits;
}
else
{
*(unsigned short data*)pOutLenBit = n*8;
}
if (n == 0) {n = 1;}
if (n > MAXRLEN){n = MAXRLEN;}
//
_i = n;
loop3:
*(unsigned char data*)pOutData = ReadRawRC(FIFODataReg);
pOutData ++;
_i --;
if(_i)goto loop3;
}
}
SetBitMask(ControlReg,0x80); // stop timer now
WriteRawRC(CommandReg,PCD_IDLE); // 空闲
return status;
}

////////////////////////////////////////////////////////////////////
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn()
{
SetBitMask(TxControlReg, 0x03); // Tx1和Tx2管脚的输出信号调制到13.56MHz的载波上
}

/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff()
{
ClearBitMask(TxControlReg, 0x03);
}
//////////////////////////////////////////////////////////////
//功 能:寻卡 t
//参数说明: req_code[IN]:寻卡方式
// 0x52 = 寻感应区内所有符合14443A标准的卡
// 0x26 = 寻未进入休眠状态的卡
// pTagType[OUT]:卡片类型代码
// 0x4400 = Mifare_UltraLight
// 0x0400 = Mifare_One(S50)
// 0x0200 = Mifare_One(S70)
// 0x0800 = Mifare_Pro(X)
// 0x4403 = Mifare_DESFire
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRequest(unsigned char req_code,unsigned char pTagType)
{
char data status;
unsigned int data unLen;
ClearBitMask(Status2Reg,0x08); // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1
WriteRawRC(BitFramingReg,0x07); // TxLastBits([2-0])表示发送的最后一个字节7位发送

SetBitMask(TxControlReg,0x03); // TxControlReg低2位(Tx2RFEn和Tx1RFEn)置1,Tx2和Tx1管脚输出信号调制在13.56MHz的载波上

ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); // PCD_TRANSCEIVE == 0x0c发送并接收数据

if ((status == MI_OK) && (unLen == 0x10)) // 发送成功并且接收16位数据
{
*(unsigned char data*)pTagType = ucComMF522Buf[0];
pTagType ++;
*(unsigned char data*)pTagType = ucComMF522Buf[1]; // 接收的卡片类型保存在pTagType中
}
else
{
status = MI_ERR;
}
return status;
}

void ASCII(unsigned char bytes,unsigned char pBuffer,unsigned char ASCIIBuffer)
{
unsigned char data i;
unsigned char data p;
p = ASCIIBuffer;
//
i = bytes;
loop_hex_sep:
*(unsigned char data*)p = *(unsigned char data*)pBuffer >> 4;
p ++;
*(unsigned char data*)p = *(unsigned char data*)pBuffer & 0x0f;
p ++;
pBuffer ++;
i --;
if(i)goto loop_hex_sep;
//
i = bytes << 1;
p = ASCIIBuffer;
loop_ASCII:
*(unsigned char data*)p |= 0x30;
CY = 0;
ACC = *(unsigned char data*)p - 0x39;
if( CY )
{
*(unsigned char data*)p += 0x07;
}
p ++;
i -- ;
if(i)goto loop_ASCII;
//
*(unsigned char data*)p = 0x00;
}

/////////////////////////////////////////////////////////////////////
//功 能:防冲撞
//参数说明: pSnr[OUT]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAnticoll(unsigned char pSnr)
{
char data status;
unsigned char data i,snr_check=0;
unsigned int data unLen;

unsigned char data *p ;
p = ucComMF522Buf;

ClearBitMask(Status2Reg,0x08); // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1
WriteRawRC(BitFramingReg,0x00); // TxLastBits([2-0])表示发送的最后一个字节的所有位都发送
ClearBitMask(CollReg,0x80); // 高位置0,所有接收的位在冲突后清除
ucComMF522Buf[0] = PICC_ANTICOLL1; // 防冲撞(0x93)
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
//
if (status == MI_OK)
{
i = 4;
loop_checksum:
snr_check ^= *(unsigned char data*)p;
*(unsigned char data*)pSnr = *(unsigned char data*)p;
pSnr ++;
p ++;
i --;
if(i)goto loop_checksum;
//
if (snr_check != *(unsigned char data*)p) status = MI_ERR;
}
SetBitMask(CollReg,0x80); // 置1,回归正常
return status;
}

/////////////////////////////////////////////////////////////////////
//功 能:选定卡片
//参数说明: pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdSelect(unsigned char pSnr)
{
data char status;
unsigned char data i;
unsigned int data unLen;

unsigned char data *p;
p = ucComMF522Buf + 2;

ucComMF522Buf[0] = PICC_ANTICOLL1; // 防冲撞
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
//
i = 4;
loop_set:
*p = *(unsigned char data*)pSnr;
ucComMF522Buf[6] ^= *(unsigned char data*)pSnr;
p ++;
pSnr ++;
i --;
if(i)goto loop_set;

CalculateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]); // CRC校验卡片序列号

ClearBitMask(Status2Reg,0x08); // 清MFCrypto1On,只能通过软件清零,该位用来指示Crypto1的接通情况,MFAuthent(验证密钥)命令成功执行后置1

status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen); // 发送卡片的序列号及其校验码

if ((status == MI_OK) && (unLen == 0x18)) // 接收24位
{ status = MI_OK; }
else
{ status = MI_ERR; }

return status;
}

/////////////////////////////////////////////////////////////////////
//功 能:验证卡片密码
//参数说明: auth_mode[IN]: 密码验证模式
// 0x60 = 验证A密钥
// 0x61 = 验证B密钥
// addr[IN]:块地址
// pKey[IN]:密码
// pSnr[IN]:卡片序列号,4字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdAuthState(unsigned char auth_mode,
unsigned char addr,
unsigned short pKey,
unsigned char pSnr)
{
char data status;
unsigned int data unLen;
unsigned char data i;
unsigned char data *p;
// data unsigned char _pKey[] = "0xff,0xff,0xff,0xff,0xff,0xff";
p = ucComMF522Buf + 2;

ucComMF522Buf[0] = auth_mode; // 验证模式
ucComMF522Buf[1] = addr; // 块地址
//
i = 6;
loop_1:
*p = *(unsigned char code*)pKey;//this is worked
pKey ++;
//*p = 0xff;//this would be more efficient
p ++;

i --;
if(i)goto loop_1;// 密码
//////////
i = 4;
loop_2:
*p = *(unsigned char data*)pSnr;// 防冲撞卡号
p ++;
pSnr ++;
i --;
if(i)goto loop_2;
////////
status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}

/////////////////////////////////////////////////////////////////////
//功 能:读取M1卡一块数据
//参数说明: addr[IN]:块地址
// pData[OUT]:读出的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdRead(unsigned char addr,unsigned char pData)
{
char data status;
unsigned int data unLen;
unsigned char data i;
unsigned char data *p;
p = ucComMF522Buf;
ucComMF522Buf[0] = PICC_READ; // 0x30,读块
ucComMF522Buf[1] = addr;
CalculateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); // 计算CRC,存放在ucComMF522Buf[2]和ucComMF522Buf[3]中

status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); // 将4个字节放松出去,并接收数据
if ((status == MI_OK) && (unLen == 0x90)) // 接收144位(18字节)
{
i = 16;
loop_read_out:
*(unsigned char data*)pData = *p;
p ++;
pData ++;
i --;
if(i)goto loop_read_out;// 将前16字节读出
}
else
{ status = MI_ERR; }

return status;
}

/////////////////////////////////////////////////////////////////////
//功 能:写数据到M1卡一块
//参数说明: addr[IN]:块地址
// pData[IN]:写入的数据,16字节
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdWrite(unsigned char addr,unsigned char pData)
{
char data status;
unsigned int data unLen;
unsigned char data i;
unsigned char data *p;
p = ucComMF522Buf;

ucComMF522Buf[0] = PICC_WRITE; // 0xa0 写块
ucComMF522Buf[1] = addr;
CalculateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); // 计算CRC

status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); // 发送写命令和地址

if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) // 接收低四位为1010
{ status = MI_ERR; }

if (status == MI_OK)
{
i = 16;
loop_read_out:
*p = *(unsigned char data*)pData;
p ++;
pData ++;
i --;
if(i)goto loop_read_out;
// 将前16字节写入
CalculateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
// 两位CRC计算字节
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen); // 发送18字节
if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) // 返回低四位为1010
{
status = MI_ERR;
}
}
return status;
}
////////////////////////////////////////////////////////
////重点问题区
//////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//功 能:命令卡片进入休眠状态
//返 回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
char PcdHalt(void)
{
unsigned char data unLen;
ucComMF522Buf[0] = PICC_HALT; // 0x50,休眠
ucComMF522Buf[1] = 0;
CalculateCRC(ucComMF522Buf , 2 , &ucComMF522Buf[2]);//计算校验位
PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen); // 发送
return MI_OK;
}

/*********************************************************************
* 用MF522计算CRC16函数
*********************************************************************/
void CalculateCRC(unsigned char pIndata,
unsigned char length,
unsigned char pOutData)
{
unsigned char data i;
ClearBitMask(DivIrqReg,0x04); // CRCIRQ清零
WriteRawRC(CommandReg,PCD_IDLE); // 空闲命令
WriteRawRC(FIFOLevelReg,0x80);
// FIFOLevelReg中FlushBuffer位置1,表示缓冲区读和写指针清除,即缓冲区无数据,用来存放一下批数据,ErrReg的BufferOvfl清楚
i = length;
loop_i1:
WriteRawRC(FIFODataReg, *(unsigned char data*)pIndata);
pIndata ++;
i--;
if(i)goto loop_i1;
//
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 255;
loop_i2:
if( ReadRawRC(DivIrqReg) & 0x04 ) goto loop_end;
i--;
if(i)goto loop_i2;
// CRCIRQ置位,当CRC有效且所有数据被处理则需要置1,退出循环,或者是执行了127次读取认为完成CRC也退出循环
loop_end:
*(unsigned char data*)pOutData = ReadRawRC(CRCResultRegL);
pOutData ++;
*(unsigned char data*)pOutData = ReadRawRC(CRCResultRegM);
// 计算结果输出到pOutData中
}

////////////////////////////////////////////////////////////////////////////////////////////
unsigned char ICcardCodeInit()//
{
unsigned char data status;
unsigned char data CardSetNum[2];
unsigned char data ASCIIBuffer[33];
status= PcdRequest(PICC_REQIDL , CardSetNum);
if(status!=0)
{
status= PcdRequest(PICC_REQIDL , CardSetNum);
if(status!=0)
{
return status;
}
}

status = PcdAnticoll(MLastSelectedSnr);
if(status!=0)
{
return status;
}

status=PcdSelect(MLastSelectedSnr);
if(status!=MI_OK)
{
return status;
}

return 0;
}
unsigned char ICcardCodeEepromRead(unsigned char block,unsigned char *_data)
{
unsigned char data status;
unsigned char data ASCIIBuffer[33];

if(status = PcdAuthState(0x61, block, DefaultKey, MLastSelectedSnr))// 校验卡密码
{
return status;
}

if(status = PcdRead(block,_data))
{
return status;
}
return 0;
}
unsigned char ICcardCodeEepromWrite(unsigned char block,unsigned char *_data)
{
unsigned char data status;
//0x60:A密钥验证
//0x61:B密钥验证
if(status = PcdAuthState(0x61, block, DefaultKey, MLastSelectedSnr)) // 校验卡密码
{
return status;
}

if(status = PcdWrite(block,_data))// 写入块
{
return status;
}
return 0;
}
unsigned char ICcardCodeHalt()
{
return (PcdHalt());
}

/////////////////////////////////////////////////////////////////////
//系统初始化
/////////////////////////////////////////////////////////////////////
void Rc522IOInit()
{
RC522_POWER_CONTROL = 0;
RC522_RESET = 0;
RC522_MISO = 0;
RC522_MOSI = 0;
RC522_SCLK = 0;
RC522_NSS = 0;
RC522_IRQ = 0;// INT0
// P_AM1815=0;
// NRF24L01_POWER_CONTROL=0;
}

void Rc522InitializeSystem()
{

RC522_RESET=0; // 复位
RC522_RESET=1;
//WriteRawRC(CommandReg,PCD_RESETPHASE); // 0x0F,软件复位

WriteRawRC(ModeReg,0x3D); // 和Mifare卡通讯,CRC初始值0x6363
WriteRawRC(TReloadRegL,30); // 48
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D); // 10001101(141):发送完开始计时,接收时停止计时,自动重装
WriteRawRC(TPrescalerReg,0x3E); // 00111110(62),3390 定时时间:3391*49/6.78=24.5ms
WriteRawRC(TxAutoReg,0x40); // 控制驱动天线
ClearBitMask(Status2Reg,0x08);

WriteRawRC(RxSelReg,0x86);//84 // 内部模拟部分的调制信号作为非接触式UART输入,发送后接收器启动延时6个位时钟
WriteRawRC(RFCfgReg,0x7F); //4F // 接收信号电压增益23dB
PcdAntennaOn();
}

>> 如何提问更容易获得答案

等于没有提出问题

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top