第五天: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
}

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
gec6818开发板电子相册是一种可以用来展示图片的设备,它可以在显示屏上显示图片,并且可以通过操作按钮进行图片的切换和控制。以下是gec6818开发板电子相册的电路图的简要说明: 电源部分:gec6818开发板电子相册的电源部分主要由直流电源模块组成,通过将交流电转换为所需的直流电压供给整个电路。 主控部分:主控部分由gec6818开发板主控芯片和外围电路组成。gec6818开发板主控芯片是相册的核心,它负责控制整个相册的运行和显示。外围电路包括时钟电路、复位电路、存储器、按键电路等,它们与主控芯片相连并辅助其正常工作。 显示部分:gec6818开发板电子相册的显示部分主要包括显示屏和显示驱动电路。显示屏可以是液晶显示屏或其他类型的显示屏,通过显示驱动电路控制显示屏显示图片。 存储部分:存储部分主要包括存储芯片和存储控制电路。存储芯片用于存储相册中的图片数据,存储控制电路与主控芯片相连,负责读取存储器中的图片数据并传输给主控芯片。 控制部分:控制部分包括按键电路和控制逻辑电路。按键电路可以通过按键来控制图片的切换和控制,控制逻辑电路负责接收按键的信号,并根据信号控制主控芯片的运行。 以上是gec6818开发板电子相册电路图的简要说明,它是实现电子相册功能的关键组成部分。通过电路图,我们可以了解到各个功能模块的连接方式和关系,进而更好地理解电子相册的工作原理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黎明的前夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值