1、介绍
RFID:RFID”又称无线射频识别。非接触式特性
应答器(PICC)卡片:被动式,主动式,半主动式,每个标签具有唯一的电子编码,附着在物体上标识目标对象
阅读器(PCD)由天线
RFID的协议分类:分别是TYpeA和TYpeB互相不兼容
2、RFID的工作流程:
读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
3、RFID的工作状态
卡的状态分为
POWER OFF:缺少载波能量
IDLE:等待读写器发来的请求
READY:收到读写器发来的请求
ACTIVE:收到读写器发来的选择
HALT:读写器发来的停止命令 卡片请求命令:
REQA:请求未被HALT的TypeA卡--0x26
WAKE-UP:请求所有的TypeA卡--0x52
4、应答器
卡片分为IC卡ID卡
ID卡(Identification Card,身份识别卡) 一种不可写入的感应卡,含固定的编号。
IC卡 (Integrated Circuit Card,集成电路卡) 是将一个微电子芯片嵌入符合ISO 7816标准的卡基中,做成卡片的形式。
使用的IC卡(s50):容量为8K位EEPROM 容量为1K。分为16个扇区,每个扇区为4块,每块16个字节,以块为存取单位每个扇区有独立的一组密码及访问控制每张卡有唯一序列号,为32位。
工作频率:13.56MHZ
每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制
5、RFID阅读器FM17550(也叫做PCD)
读写器: 通信频率 支持协议 读写距离 通信速率 寄存器配置 天线发送,接收 系统复位 调制方式 缓存区操作 常见的有FM17550,FM17522,MFRC523,MFRC522。支持串口。
串口配置为: 波特率为9600 无奇偶校验位 无硬/软流控 数据位为8bit 1位停止位
硬件复位 外部IO,保持低电平一定时间 确认复位成功
读地址为0x37h的版本寄存器的值。
寄存器地址:0xnm n表示第几页 m表示第n页中的某一个地址
比如:0x37显示版本--->第3页中的第7个寄存器
6、获取RFID的卡号
1、RFID阅读器的初始化uart_rfid_init(UART_DEV);
1.1 设置GPIOA30的工作模式(输出)
if(access("/sys/class/gpio/gpio30/value",F_OK))
system("echo 30 > /sys/class/gpio/export"); //导出GPIO30
system("echo out > /sys/class/gpio/gpio30/direction"); //设置GPIOA的方向为输出
1.2、打开串口设备文件art_fd = uart_open(&uart_fd, dev)
int uart_open(int *fd, char* port)
{
*fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);
return *fd;
}
1.3、uart_init(uart_fd)初始化串口
int uart_set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)
{
//获取串口属性
struct termios options;
memset(&options, 0, sizeof(options));
tcgetattr( fd,&options);
//设置输入输出波特率
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
//无流控
options.c_cflag &= ~CRTSCTS;
//设置数据为为8位
options.c_cflag |= CS8;
//设置1位停止位
options.c_cflag &= ~CSTOPB;
//设置无奇偶校验为
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
}
1.4 复位RFID阅读器
do_rst(0);
usleep(50*1000);
do_rst(1);
usleep(50*1000);
1.5 获取阅读器的版本
#define VersionReg 0x37
version = reg_get(VersionReg)
//函数内部实现
unsigned char reg_get(unsigned char reg_addr)
{
//通过write往串口写入 版本寄存器的地址0x37
uart_putchar(reg_addr)
//通过read读取RFID阅读器 回应的版本
uart_getchar(&ch, WAIT_USEC);
return ch;
}
2、获取S50卡的卡号
2.1 初始化A类卡
rfid_carda_init();//初始化A类卡 启动阅读器 100%调幅 信号增益最大 开启天线
2.2 获取卡片内的所有A类卡
#define PICC_REQALL 0x52
rfid_carda_request(PICC_REQALL, TagType)
unsigned char rfid_carda_request(unsigned char req_code, unsigned char *card_type)
{
buf[0] = req_code;//buf[0]=0x52 扫描天线内所有卡
//PCD_TRANSCEIVE 发送并接受数据
status = rfid_cmd(PCD_TRANSCEIVE, buf, 1, buf, &len);
//实现
unsigned char rfid_cmd(unsigned char Command,
unsigned char *pInData,
unsigned char InLenByte,
unsigned char *pOutData,
unsigned int *pOutLenBit)
{
//1、A53将0x52扫描天线内所有卡的指令 发送到 RFID阅读器上
for (i=0; i<InLenByte; i++)
{ reg_set(FIFODataReg, pInData[i]); }
//2、延时一段时间 让rfid准备数据
//3、A53获取rfid回应的数据长度
n = reg_get(FIFOLevelReg);
//4、通过数据长度 从RFID的FIFO中逐个字节读取
for (i=0; i<n; i++)
{ pOutData[i] = reg_get(FIFODataReg); }
}
}
2.3 rfid_anticoll(buf) 获取卡号
unsigned char rfid_anticoll(unsigned char *card_num)
{
//获取卡号
buf[0] = PICC_ANTICOLL1; //s50卡,4字节,级联为1
buf[1] = 0x20;
status = rfid_cmd(PCD_TRANSCEIVE, buf, 2, buf, &len);
//组包
for(i=0; i<4; i++)
{
*(card_num+i) = buf[i];
snr_check ^= buf[i];
}
}
3、RFID的读写
3.1 选卡(必须获取卡号后才执行)
ret = PcdSelect(card_id);
3.2 校验密码
int snr = 3;
unsigned char a_key[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
ret = PcdAuthState(KEYA,snr*4+3,a_key,card_id);
3.3 读数据
PcdRead(snr*4+block,b_data)
3.4 写入数据
ret = PcdWrite(snr*4+block,b_data);