文章目录
- 522模块总共有8个引脚,除去复位、GND接地、3.3V电源、NC端悬空、SCK时钟端,剩余3个引脚,起数据作用。
- 这里主要使用IIC的方法,相信写过IIC的同学都很熟悉这段代码。不熟悉也没关系,后文会附上52单片机的LCD1602显示UID的实现代码,包含UART测试代码。 显而易见,通过总线办法读取数据只需要依照手册写代码就可以读出来,这里官方提供了函数代码。同样后文附上。 再附上IIC的数据传输规则。
-
- 假设我们写522代码的目的是为了设计一个门禁系统,那提出的第一个问题一定是:我们需要从ic中读出什么数据?什么数据又是正确的数据? ic卡分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位。 第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。 这样一个东西,叫做UID,这是一个存储在ic中的不可更改的数据,他是一个4字节16进制数,所以我们将他作为我们的判断依据。 幸运的是厂商给我们提供了参考代码,返回这个ic的UID。见后
- 简单做个解释。1、检测是否有人打卡(寻卡),2、放冲突,3、选择这张卡(目的是确认写入卡片),4、进入三次相互验证(对于门禁系统来说仅涉及1,2步骤)
- 卡片的电气部分只由一个天线和ASIC组成。 天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。 工作原理:读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。 了解原理了,来看看官方代码。 / // req_code[in]:寻卡方式 // 0x52:寻找感应区内所有符合14443A标准的卡(一般传入参数) // 0x26:寻找进入休眠状态的卡 // pTagType[out]:卡片类型代码 / char PcdRequest(unsigned char req_code,unsigned char *pTagType) { char status; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x07); SetBitMask(TxControlReg,0x03); ucComMF522Buf[0] = req_code; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen); if ((status == MI_OK) && (unLen == 0x10)) { *pTagType = ucComMF522Buf[0]; *(pTagType+1) = ucComMF522Buf[1]; } else { status = MI_ERR; } return status; } 当req_code传入0x52时,如果寻找到卡,返回status == MI_OK == 0。调用: if (PcdRequest(0x52, Temp) == MI_OK){ }
- 在通过了寻卡这个if后,进入到放冲突环节,对于门禁设计而言,进入这个函数最大的需要在于,这个函数的返回,是ic卡的UID。 / // 防冲撞 // pSnr[out]:卡片UID,4字节 / char PcdAnticoll(unsigned char *pSnr) { char status; unsigned char i,snr_check=0; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x00); ClearBitMask(CollReg,0x80); ucComMF522Buf[0] = PICC_ANTICOLL1; ucComMF522Buf[1] = 0x20; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen); if (status == MI_OK) { for (i=0; i<4; i++) { *(pSnr+i) = ucComMF522Buf[i]; snr_check ^= ucComMF522Buf[i]; } if (snr_check != ucComMF522Buf[i]) { status = MI_ERR; } } SetBitMask(CollReg,0x80); return status; } 当这个函数执行了后,所传入的pSnr参数就会被传入UID。 剩下的就是 if (UID == predict)
- 使用UART进行调试有两种方法,一、上位机软件调试(开发板),二、串口调试,适用于打卡系统,可以直接与后端交互
- 我将其浓缩为三个步骤
- 具体点应该叫做,代码版串口调试,或无需开发板版调试,hhh。 这种方法有个前提:你已经学会了怎么读取卡片的UID。 那我们的方法就很简单了,通过sbuf串口把我们接受到的UID发送出去。 void UART_send_byte(unsigned char dat) { SBUF = dat; while (TI == 0); TI = 0; } // 发送一个字符串 ART_send_string(unsigned char *buf) { while (*buf != ‘void UART_send_byte(unsigned char dat) { SBUF = dat; while (TI == 0); TI = 0; } // 发送一个字符串 ART_send_string(unsigned char *buf) { while (*buf != ‘\0’) { UART_send_byte(*buf++); } } ‘) { UART_send_byte(*buf++); } } 如果有小伙伴在尝试这种方法,并将这个UID通过ETH-01网络模块发送给服务器,相信会发现一个很有趣的事情,评论区见。 这里我补充一个函数 void u16ToString(uchar Volume[], char *hexStr, uint u) { /* hexStr Ϊת»»ºóµÄ×Ö·û´® XXXX*/ uint j,k; char strlist[] = “0123456789ABCDEF”; /*16½øÖÆ×Ö·û±í£¬Óòé±í·¨¸ßЧ¿ìËÙ*/ for(j=0;j<u;j++){ if(Volume[j] != ‘void u16ToString(uchar Volume[], char *hexStr, uint u) { /* hexStr Ϊת»»ºóµÄ×Ö·û´® XXXX*/ uint j,k; char strlist[] = “0123456789ABCDEF”; /*16½øÖÆ×Ö·û±í£¬Óòé±í·¨¸ßЧ¿ìËÙ*/ for(j=0;j<u;j++){ if(Volume[j] != ‘\0’){ for(k=0;k<2;k++){ hexStr[j*2+k] = strlist[Volume[j] & 0x0f]; /*Volume & 0x0f£ºÈ¡µÃ ¸ÃλµÄ16½øÖÆÖµ£¬¶ÔÓ¦µÄ¾ÍÊÇstrÊý×éµÄasciiÂë*/ Volume[j] = Volume[j] >> 4; } } else{ break;} } } ‘){ for(k=0;k<2;k++){ hexStr[j*2+k] = strlist[Volume[j] & 0x0f]; /*Volume & 0x0f£ºÈ¡µÃ ¸ÃλµÄ16½øÖÆÖµ£¬¶ÔÓ¦µÄ¾ÍÊÇstrÊý×éµÄasciiÂë*/ Volume[j] = Volume[j] >> 4; } } else{ break;} } }
- 百度云 链接: https://pan.baidu.com/s/14u8R8tpNyBmoxiftK0BCSA 提取码: u4x8


522模块总共有8个引脚,除去复位、GND接地、3.3V电源、NC端悬空、SCK时钟端,剩余3个引脚,起数据作用。


这里主要使用IIC的方法,相信写过IIC的同学都很熟悉这段代码。不熟悉也没关系,后文会附上52单片机的LCD1602显示UID的实现代码,包含UART测试代码。
显而易见,通过总线办法读取数据只需要依照手册写代码就可以读出来,这里官方提供了函数代码。同样后文附上。
再附上IIC的数据传输规则。


假设我们写522代码的目的是为了设计一个门禁系统,那提出的第一个问题一定是:我们需要从ic中读出什么数据?什么数据又是正确的数据?
ic卡分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位。
假设我们写522代码的目的是为了设计一个门禁系统,那提出的第一个问题一定是:我们需要从ic中读出什么数据?什么数据又是正确的数据?
ic卡分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位。


第0扇区的块0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。
这样一个东西,叫做UID,这是一个存储在ic中的不可更改的数据,他是一个4字节16进制数,所以我们将他作为我们的判断依据。
幸运的是厂商给我们提供了参考代码,返回这个ic的UID。见后


简单做个解释。1、检测是否有人打卡(寻卡),2、放冲突,3、选择这张卡(目的是确认写入卡片),4、进入三次相互验证(对于门禁系统来说仅涉及1,2步骤)
卡片的电气部分只由一个天线和ASIC组成。
天线:卡片的天线是只有几组绕线的线圈,很适于封装到IS0卡片中。
工作原理:读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
了解原理了,来看看官方代码。
/
// req_code[in]:寻卡方式
// 0x52:寻找感应区内所有符合14443A标准的卡(一般传入参数)
// 0x26:寻找进入休眠状态的卡
// pTagType[out]:卡片类型代码
/
char PcdRequest(unsigned char req_code,unsigned char *pTagType)
{
char status;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{
status = MI_ERR; }
return status;
}
当req_code传入0x52时,如果寻找到卡,返回status == MI_OK == 0。调用:
if (PcdRequest(0x52, Temp) == MI_OK){
}
在通过了寻卡这个if后,进入到放冲突环节,对于门禁设计而言,进入这个函数最大的需要在于,这个函数的返回,是ic卡的UID。
/
// 防冲撞
// pSnr[out]:卡片UID,4字节
/
char PcdAnticoll(unsigned char *pSnr)
{
char status;
unsigned char i,snr_check=0;
unsigned int unLen;
unsigned char ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check != ucComMF522Buf[i])
{
status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
当这个函数执行了后,所传入的pSnr参数就会被传入UID。
剩下的就是
if (UID == predict)
使用UART进行调试有两种方法,一、上位机软件调试(开发板),二、串口调试,适用于打卡系统,可以直接与后端交互
我将其浓缩为三个步骤
我将其浓缩为三个步骤


具体点应该叫做,代码版串口调试,或无需开发板版调试,hhh。
这种方法有个前提:你已经学会了怎么读取卡片的UID。
那我们的方法就很简单了,通过sbuf串口把我们接受到的UID发送出去。
void UART_send_byte(unsigned char dat) { SBUF = dat; while (TI == 0); TI = 0; } // 发送一个字符串 ART_send_string(unsigned char *buf) { while (*buf != 'void UART_send_byte(unsigned char dat) { SBUF = dat; while (TI == 0); TI = 0; } // 发送一个字符串 ART_send_string(unsigned char *buf) { while (*buf != '\0') { UART_send_byte(*buf++); } }'
)
{
UART_send_byte(*buf++);
}
}如果有小伙伴在尝试这种方法,并将这个UID通过ETH-01网络模块发送给服务器,相信会发现一个很有趣的事情,评论区见。
这里我补充一个函数void u16ToString(uchar Volume[], char *hexStr, uint u) { /* hexStr Ϊת»»ºóµÄ×Ö·û´® XXXX*/ uint j,k; char strlist[] = "0123456789ABCDEF"; /*16½øÖÆ×Ö·û±í£¬Óòé±í·¨¸ßЧ¿ìËÙ*/ for(j=0;j<u;j++){ if(Volume[j] != 'void u16ToString(uchar Volume[], char *hexStr, uint u) { /* hexStr Ϊת»»ºóµÄ×Ö·û´® XXXX*/ uint j,k; char strlist[] = "0123456789ABCDEF"; /*16½øÖÆ×Ö·û±í£¬Óòé±í·¨¸ßЧ¿ìËÙ*/ for(j=0;j<u;j++){ if(Volume[j] != '\0'){ for(k=0;k<2;k++){ hexStr[j*2+k] = strlist[Volume[j] & 0x0f]; /*Volume & 0x0f£ºÈ¡µÃ ¸ÃλµÄ16½øÖÆÖµ£¬¶ÔÓ¦µÄ¾ÍÊÇstrÊý×éµÄasciiÂë*/ Volume[j] = Volume[j] >> 4; } } else{ break;} } }'
){
for(k=0;k<2;k++){
hexStr[j*2+k] = strlist[Volume[j] & 0x0f]; /*Volume & 0x0f£ºÈ¡µÃ ¸ÃλµÄ16½øÖÆÖµ£¬¶ÔÓ¦µÄ¾ÍÊÇstrÊý×éµÄasciiÂë*/
Volume[j] = Volume[j] >> 4;
}
}
else{
break;}
}}
百度云
链接: https://pan.baidu.com/s/14u8R8tpNyBmoxiftK0BCSA
提取码: u4x8
发表回复