第五天:gec6818开发板对RFID高频读卡器进行防碰撞获取卡号,读取,写入内容操作

在ARM板上通过防碰撞指令获取高频RFID卡的卡号

高频RFID一般频率在13.56MHz左右,识别距离可扩展至1.5米,具有防碰撞特性,可以同时读取多个电子标签。标签可以存储少量数据,多用于需要存储数据、近距离的识别应用,如:图书馆管理系统、场地通道安全管理系统等。
在这里插入图片描述
在这里插入图片描述
mifare522模块的数据帧格式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

gec6818开发板读取卡号完整代码(直接运行即可):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h> //串口配置需要的头文件
/*
 *	init_serial:自定义的用来打开串口文件并对串口进行初始化的函数
 *	arg:
 *		@fild:串口设备文件名,指定您要使用的串口
 *		@baudrate:整数,指定您要配置的串口的通信波特率
 *			9600/115200/19200
 *	配置的串口协议:数据位8,停止位1,不要校验,不要硬件控制流
 *	return:
 *		成功,返回打开 并初始化好的 串口的文件描述符,后期根据该返回值来与链接在该串口上的传感器进行通信
 *		失败返回-1
 **/
unsigned int card_ID;
int init_serial(const char *file, int baudrate)
{
    
    
    int fd;

    fd = open(file, O_RDWR);
    if (fd == -1)
    {
    
    
        perror("open device error:");
        return -1;
    }

    struct termios myserial;
    //清空结构体
    memset(&myserial, 0, sizeof (myserial));
    //O_RDWR
    myserial.c_cflag |= (CLOCAL | CREAD);
    //设置控制模式状态,本地连接,接受使能
    //设置 数据位
    myserial.c_cflag &= ~CSIZE;   //清空数据位
    myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
    myserial.c_cflag |= CS8;      //数据位:8

    myserial.c_cflag &= ~CSTOPB;//   //1位停止位
    myserial.c_cflag &= ~PARENB;  //不要校验
    //myserial.c_iflag |= IGNPAR;   //不要校验
    //myserial.c_oflag = 0;  //输入模式
    //myserial.c_lflag = 0;  //不激活终端模式

    switch (baudrate)
    {
    
    
        case 9600:
            cfsetospeed(&myserial, B9600);  //设置波特率
            cfsetispeed(&myserial, B9600);
            break;
        case 115200:
            cfsetospeed(&myserial, B115200);  //设置波特率
            cfsetispeed(&myserial, B115200);
            break;
        case 19200:
            cfsetospeed(&myserial, B19200);  //设置波特率
            cfsetispeed(&myserial, B19200);
            break;
    }
    /* 刷新输出队列,清除正接受的数据 */
    tcflush(fd, TCIFLUSH);

    /* 改变配置 */
    tcsetattr(fd, TCSANOW, &myserial);

    return fd;
}

unsigned char CalBCC(unsigned char *buf, int n)
{
    
    
    int i;
    unsigned char bcc=0;
    for(i=0;i<n;i++)
    {
    
    
        bcc ^=*(buf+i);
    }
    return (~bcc);
}

int PiccRequest (int fd)
{
    
    
    unsigned char WBuf[10];
    unsigned char RBuf[10];
	memset(WBuf,0,sizeof(WBuf));
	memset(RBuf,0,sizeof(RBuf));
    WBuf[0] = 0x07; //帧长= 7 Byte
    WBuf[1] = 0x02; //包号= 0,命令类型= 0x02
    WBuf[2] ='A' ;//命令= 'A'
    WBuf[3] = 0x01; //信息长度= 1
    WBuf[4] = 0x52; //请求模式:ALL=0x52
    WBuf[5] = CalBCC(WBuf,5);//校验和
    WBuf[6] = 0x03; //结束标志
    write(fd,WBuf, 7) ;	//发送命令
    usleep (100000) ;	//延时等待
    int ret = read(fd, RBuf,8);//接收回复数据
    if(ret == 8)
    {
    
    
        return RBuf[2];//返回状态值,若为0,表示请求成功
    }
    else
    {
    
    
        printf ("read error, ret:%d\n",ret) ;
        return -1 ;
    }

}
int PiccAnticoll(int fd)
{
    
    
    unsigned char RBuf[10];
    unsigned char WBuf[10];
	memset(WBuf,0,sizeof(WBuf));
	memset(RBuf,0,sizeof(RBuf));
    WBuf[0] = 0x08; //帧长= 8 Byte
    WBuf[1] = 0x02; //包号= 0,命令类型= 0x02
    WBuf[2] = 'B'; //命令= 'B '
    WBuf[3] = 0x02; //信息长度= 2
    WBuf[4] = 0x93; //防碰撞0x93 --- - 级防碰撞
    WBuf[5] = 0x00; //位计数0
    WBuf[6] = CalBCC (WBuf,6) ; //校验和
    WBuf[7] = 0x03 ;//结束标志
    write (fd, WBuf,8);
    usleep(50000) ;
    int ret = read(fd,RBuf,10) ;
    if (RBuf[2] == 0x00) //应答帧状态部分为0则获取ID成功
    {
    
    
        card_ID = (RBuf[7]<<24)| (RBuf[6]<<16) | (RBuf[5]<<8) | RBuf[4] ;
        printf ("PiccAnticoll The card ID is %u\n",card_ID) ;
        return 0 ;
    }

}

int main(int argc, char const *argv[])
{
    
    
    int uart1_fd = init_serial("/dev/ttySAC1" ,9600) ;//打开并初始化串口
	
    while (1){
    
    
        if (PiccRequest (uart1_fd) )//请求天线范围的卡
        {
    
    
            printf("The Request Failed!\n");
            continue;
        }
        if (PiccAnticoll (uart1_fd))//进行防碰撞,获取天线范围内最大的ID
        {
    
    
            printf("2 RFID PicCAnticoll Failed!\n");
            break;
        }
        printf("card ID is %u \n" ,card_ID);
		break;
    }
    close (uart1_fd) ;
	if(card_ID == 2773529475)
		return 1;
	else
		return -1;
}

关于RFID高频读卡器的模块资料我都打包好了,放在下载资源里面,想认真学习的可自行下载,里面包括了读卡案例代码和可执行文件等详细资料。

点击跳转下载链接
在这里插入图片描述
在这里插入图片描述

stm32驱动代码实例:

代码太多,以下提供了一些常用操作指令代码,这些代码可移植性很强,方便大家直接调用。你们也可以结合自己的需要去使用。比如搞一个门禁系统,校园卡,图书管理系统,智能家居系统,车辆管理系统等
串口通信代码:

int init_serial(const char *file, int baudrate)
{
    
    
    int fd;

    fd = open(file, O_RDWR);
    if (fd == -1)
    {
    
    
        perror("open device error:");
        return -1;
    }

    struct termios myserial;
    //清空结构体
    memset(&myserial, 0, sizeof (myserial));
    //O_RDWR
    myserial.c_cflag |= (CLOCAL | CREAD);
    //设置控制模式状态,本地连接,接受使能
    //设置 数据位
    myserial.c_cflag &= ~CSIZE;   //清空数据位
    myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
    myserial.c_cflag |= CS8;      //数据位:8

    myserial.c_cflag &= ~CSTOPB;//   //1位停止位
    myserial.c_cflag &= ~PARENB;  //不要校验
    //myserial.c_iflag |= IGNPAR;   //不要校验
    //myserial.c_oflag = 0;  //输入模式
    //myserial.c_lflag = 0;  //不激活终端模式

    switch (baudrate)
    {
    
    
        case 9600:
            cfsetospeed(&myserial, B9600);  //设置波特率
            cfsetispeed(&myserial, B9600);
            break;
        case 115200:
            cfsetospeed(&myserial, B115200);  //设置波特率
            cfsetispeed(&myserial, B115200);
            break;
        case 19200:
            cfsetospeed(&myserial, B19200);  //设置波特率
            cfsetispeed(&myserial, B19200);
            break;
    }
    /* 刷新输出队列,清除正接受的数据 */
    tcflush(fd, TCIFLUSH);

    /* 改变配置 */
    tcsetattr(fd, TCSANOW, &myserial);

    return fd;
}

常用操作代码:

#include "stm32f10x.h"
#include "usart3.h"
#include "usart.h"
#include "rfid.h"
#include "stdio.h"

unsigned char Uart3RxBuf[UART3_RX_BUF_LEN];
unsigned char Uart3RxDataConut = 0;
unsigned char Rx3Flag = 0;

unsigned char Cmd_Read_Id[8] = {
    
    0x01,0x08,0xa1,0x20,0x00,0x00,0x00,0x00};
unsigned char Cmd_Read_Block[8]	= {
    
    0x01,0x08,0xa3,0x20,0x00,0x00,0x00,0x00};
unsigned char Cmd_Write_Block[23] = {
    
    0x01,0x17,0xa4,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

unsigned char WBlockData[16] = {
    
    0x11,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
//CircularBuffer *Uart2_Circular_Buffer;
unsigned char Cmd_Write_RFID[0x0B]={
    
    0x03, 0x0B, 0xC5, 0x20, 0x05, 0x12, 0x34, 0x56, 0x78, 0x09, 0x16};
 //                          命令类型  包长度  命令  设备地址  起始地址  数据长度   保留  校验和
unsigned char Cmd_Read_RFID[]={
    
    0x02,   0x08,   0xB5,  0x20,    0x03,      0x06,     0x00,  0x65};

//延时,10000000大约为1S
void Delay(__IO unsigned int nCount)
{
    
    
  for (; nCount != 0; nCount--);
}

void Uart3_Send_Data(unsigned char *buf,unsigned char num)
{
    
    
	unsigned char i;
	for(i=0;i<num;i++)
	{
    
     
	 	USART_SendData(USART3, buf[i]);
	 	while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
	}	
}

unsigned char RxCheckSum(unsigned char *ptr,unsigned char len) //计算校验值 
{
    
    
	unsigned char i;
	unsigned char checksum;
	checksum = 0;
	for(i=0;i<(len-1);i++)
	{
    
    
		   checksum ^= ptr[i];
	}
	checksum = ~checksum;
	if(ptr[len-1] == checksum)
		return 	STATUS_OK;
	else 
		return 	STATUS_ERR;
}

void TxCheckSum(unsigned char *ptr,unsigned char len)
{
    
    
	unsigned char i;
	unsigned char checksum;
	checksum = 0;
	for(i=0;i<(len-1);i++)
	{
    
    
		   checksum ^= ptr[i];
	}
	checksum = ~checksum;
	ptr[len-1] = checksum;
}
//ReadId():读IC卡ID号(卡号)
//参数:*idout,读取的卡号保存到它所指向的存储空间
//返回值:0:成功读取卡号,1:读卡号失败
unsigned char ReadId(void)
{
    
    
	unsigned char status;
	unsigned char i;
	unsigned char idout[6];
	Cmd_Read_Id[5] = 0x01;//开启蜂鸣器提示
	//Cmd_Read_Id[5] = 0x00;//关闭蜂鸣器提示
	TxCheckSum(Cmd_Read_Id,Cmd_Read_Id[1]);		//计算校验和
	Uart3_Send_Data(Cmd_Read_Id,Cmd_Read_Id[1]);		 //发送读卡号ID命令
	Delay(2000000);//等待模块返回数据,大于150MS
 	if(Rx3Flag == 1)
 	{
    
    	
		Rx3Flag = 0;
		status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
		if(status != STATUS_OK)  //判断校验和是否正确
		{
    
    
			return STATUS_ERR;
		}
		status = Uart3RxBuf[4];
		if(status != STATUS_OK)	//判断是否正确的读到卡
		{
    
    
		 	return STATUS_ERR;
		}
		if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa1))//判断是否为读卡号返回的数据包
		{
    
    
			for(i=0;i<6;i++)//获取卡号ID,6字节		 
			{
    
    
				idout[i] = Uart3RxBuf[i+5];//从数组的第5个字节开始为卡号,长度为6字节
			}
			for(i=0;i<6;i++)
		{
    
    
			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
			USART_SendData(USART1,idout[i]); 
		}
			return STATUS_OK;		 //成功返回0
		}
 	} 
	return STATUS_ERR;			//失败返回1
}


//ReadId():读IC卡数据块
//参数:*idout,读取的数据保存到它所指向的存储空间
//参数:block,块号
//返回值:0:成功读取,1:读读取失败
unsigned char ReadDataFromBlock(unsigned char *dataout,unsigned char block)
{
    
    
	unsigned char status;
	unsigned char i;
	Cmd_Read_Block[4] = block;
	Cmd_Read_Block[5] = 0x01;//开启蜂鸣器提示
//	Cmd_Read_Block[5] = 0x00;//关闭蜂鸣器提示
	TxCheckSum(Cmd_Read_Block,Cmd_Read_Block[1]);	//数据校验
	Uart3_Send_Data(Cmd_Read_Block,Cmd_Read_Block[1]);		 //发送读数据块命令
	Delay(2000000);//等待模块返回数据,大于150MS
 	if(Rx3Flag == 1)
 	{
    
    	
		Rx3Flag = 0;
		status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
		if(status != STATUS_OK)		 //判断校验和是否正确
		{
    
    
			return 	STATUS_ERR;
		}
		status = Uart3RxBuf[4];		//获取返回包状态
		if(status != STATUS_OK)	//判断是否正确的读到卡
		{
    
    
			return STATUS_ERR;
		}
		if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa3))//判断是否为读块数据返回的数据包
		{
    
    
			for(i=0;i<16;i++)//获取块数据,16字节	,一个数据块的大小为16字节	 
			{
    
    
				dataout[i] = Uart3RxBuf[i+5];//从数组的第5个字节开始为数据,长度为16字节
			}
			return STATUS_OK;		 //成功返回0
		}
	}
	return STATUS_ERR;			//失败返回1
}
//ReadId():写数据到指定的数据块
//参数:*idout,指向要写入数据的缓冲区
//参数:block,块号
//返回值:0:写入成功,1:写入失败
unsigned char WriteDataToBlock(unsigned char *datain,unsigned char block)
{
    
    
	unsigned char status;
	unsigned char i;
	Cmd_Write_Block[4] = block;
	for(i=0;i<16;i++)
	{
    
    
		Cmd_Write_Block[6+i] = datain[i];
	}
	TxCheckSum(Cmd_Write_Block,Cmd_Write_Block[1]);	//数据校验
	Uart3_Send_Data(Cmd_Write_Block,Cmd_Write_Block[1]);		 //发送写命令
	Delay(2000000);//等待模块返回数据,大于150MS
 	if(Rx3Flag == 1)
 	{
    
    	
		Rx3Flag = 0;
		status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对返回的数据进行校验
		if(status != STATUS_OK) //判断校验是否通过
		{
    
    
			return STATUS_ERR;
		}
		status = Uart3RxBuf[4];
		if(status != STATUS_OK) //判断校验是否通过
		{
    
    
			return STATUS_ERR;
		}
		if((Uart3RxBuf[0] == 0x01)&&(Uart3RxBuf[2] == 0xa4))//判断是否为写块数据返回的数据包
		{
    
    
				return STATUS_OK;		 //成功返回0
		}
 	} 
	return STATUS_ERR;			//失败返回1
}
//读RFID用户空间
unsigned char Read_RFID(unsigned char addr,unsigned char len)
{
    
    
  unsigned char status;
  unsigned char i;
    Cmd_Read_RFID[4]=addr;
    Cmd_Read_RFID[5]=len;
	TxCheckSum(Cmd_Read_RFID,Cmd_Read_RFID[1]);		//计算校验和
	Uart3_Send_Data(Cmd_Read_RFID,Cmd_Read_RFID[1]);		 //发送读用户数据命令
	Delay(2000000);//等待模块返回数据,大于150MS
 	if(Rx3Flag == 1)
 	{
    
    	
        
		Rx3Flag = 0;
		status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对接收到的数据校验
		if(status != STATUS_OK)  //判断校验和是否正确
		{
    
    
			return STATUS_ERR;
		}
		status = Uart3RxBuf[4];
		if(status != STATUS_OK)	//判断是否正确的读到卡
		{
    
    
		 	return STATUS_ERR;
		}
		if((Uart3RxBuf[0] == 0x02)&&(Uart3RxBuf[2] == 0xB5))//判断是否为读RFID用户信息返回的数据包
		{
    
    
			
			for(i=0;i<Cmd_Read_RFID[5];i++)   //将读取的RFID打印到串口
		{
    
    
			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
			USART_SendData(USART1,Uart3RxBuf[i+5]); 
		}
			return STATUS_OK;		 //成功返回0
		}
 	} 
	return STATUS_ERR;	
}
//写RFID 用户空间
unsigned char Write_RFID(unsigned char addr,unsigned char * data,unsigned char len)
{
    
     
    unsigned char status;
	unsigned char i;
    unsigned char cmd[22]={
    
    0x03, 0x0B, 0xC5, 0x20};
	cmd[4] =addr;//地址
    cmd[1]=6+len;//长度
	for(i=0;i<len;i++)
	{
    
    
		cmd[5+i] = data[i];
	}
	TxCheckSum(cmd,cmd[1]);	//数据校验
	Uart3_Send_Data(cmd,cmd[1]);	 //发送写命令
	Delay(2000000);//等待模块返回数据,大于150MS
 	if(Rx3Flag == 1)
 	{
    
    	
		Rx3Flag = 0;
		status = RxCheckSum(Uart3RxBuf,Uart3RxBuf[1]);//对返回的数据进行校验
		if(status != STATUS_OK) //判断校验是否通过
		{
    
    
			return STATUS_ERR;
		}
		status = Uart3RxBuf[4];
		if(status != STATUS_OK) //判断校验是否通过
		{
    
    
			return STATUS_ERR;
		}
		if((Uart3RxBuf[0] == 0x03)&&(Uart3RxBuf[2] == 0xc5))//判断是否为写块数据返回的数据包
		{
    
            
             for(i=0;i<len;i++)   //将写入的数据打印到串口
		{
    
    
			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); 
			USART_SendData(USART1,cmd[i+5]); 
		}
				return STATUS_OK;		 //成功返回0
		}
 	} 
	return STATUS_ERR;			//失败返回1
}

猜你喜欢

转载自blog.csdn.net/xqmids99/article/details/133125161