📄 fm1702.c
字号:
#include <string.h>#include <stdio.h>#include <absacc.h>#include <intrins.h>#include "FM1702.h"#include "reg52.h"#define NO_TIMER2 1bit CmdValid;unsigned char cardtype;uchar idata tagtype[2]; /* 卡片标识字符 *//* FM1715变量定义 */uchar idata buffer[30]; /* FM1715命令发送接收缓冲区 */uchar idata UID[5]; /* 序列号 */uchar idata Secnr; /* 扇区号 */extern unsigned char read_reg(unsigned char idata SpiAddress);extern void write_reg(unsigned char idata SpiAddress,unsigned char dat);extern void delay1(uchar dlength);/****************************************************************//*名称: Clear_FIFO *//*功能: 该函数实现清空RC531中FIFO的数据 *//* *//*输入: *//* N/A *//* *//*输出: *//* TRUE, FIFO被清空 *//* FALSE, FIFO未被清空 *//****************************************************************/uchar Clear_FIFO(void){ uchar temp; uint i; temp =read_reg(Control); //清空FIFO temp = (temp | 0x01); write_reg(Control, temp); for(i = 0; i < RF_TimeOut; i++) //检查FIFO是否被清空 { temp = read_reg(FIFO_Length); if(temp == 0) { return TRUE; } } return FALSE;}/****************************************************************//*名称: Write_FIFO *//*功能: 该函数实现向RC531的FIFO中写入x bytes数据 *//* *//*输入: *//* count, 待写入字节的长度 *//* buff, 指向待写入数据的指针 *//* *//*输出: *//* N/A *//****************************************************************/void Write_FIFO(uchar count,uchar idata *buff){ uchar i; for(i = 0; i < count; i++) { write_reg(FIFO,*(buff + i)); }}/****************************************************************//*名称: Read_FIFO *//*功能: 该函数实现从RC531的FIFO中读出x bytes数据 *//* *//*输入: *//* buff, 指向读出数据的指针 *//* *//*输出: *//* N/A *//****************************************************************/uchar Read_FIFO(uchar idata *buff){ uchar temp; uchar i; temp =read_reg(FIFO_Length); if (temp == 0) { return 0; } if (temp >= 24) //temp=255时,会进入死循环 { //因此增加FIFO_Length越限判断 temp = 24; //yanshouli,2003-12-2 } for(i = 0;i < temp; i++) { *(buff + i) =read_reg(FIFO); } return temp; }/****************************************************************//*名称: Judge_Req *//*功能: 该函数实现对卡片复位应答信号的判断 *//* *//*输入: *//* *buff, 指向应答数据的指针 *//* *//*输出: *//* TRUE, 卡片应答信号正确 *//* FALSE, 卡片应答信号错误 *//****************************************************************/uchar Judge_Req(uchar idata *buff){ uchar temp1,temp2; temp1 = *buff; temp2 = *(buff + 1); //if(((temp1 == 0x03) || (temp1 == 0x04) || (temp1 == 0x05) || (temp1 == 0x53)) && (temp2 == 0x00)) //change by hbp S70 temp1 = 0x02 if((temp1 != 0x00) && (temp2 == 0x00)) { return TRUE; } return FALSE;}/****************************************************************//*名称: Check_UID *//*功能: 该函数实现对收到的卡片的序列号的判断*//*输入: N/A *//*输出: TRUE: 序列号正确*//* FALSE: 序列号错误*//****************************************************************/uchar Check_UID(void){ /*~~~~~~~~~*/ uchar temp; uchar i; /*~~~~~~~~~*/ temp = 0x00; for(i = 0; i < 5; i++) { temp = temp ^ UID[i]; } if(temp == 0) { return TRUE; } return FALSE;}/****************************************************************//*名称: Save_UID *//*功能: 该函数实现保存卡片收到的序列号*//*输入: row: 产生冲突的行*//* col: 产生冲突的列*//* length: 接収到的UID数据长度*//*输出: N/A *//****************************************************************/void Save_UID(uchar row, uchar col, uchar length){ /*~~~~~~~~~~*/ uchar i; uchar temp; uchar temp1; /*~~~~~~~~~~*/ if((row == 0x00) && (col == 0x00)) { for(i = 0; i < length; i++) { UID[i] = buffer[i]; } } else { temp = buffer[0]; temp1 = UID[row - 1]; switch(col) { case 0: temp1 = 0x00; row = row + 1; break; case 1: temp = temp & 0xFE; temp1 = temp1 & 0x01; break; case 2: temp = temp & 0xFC; temp1 = temp1 & 0x03; break; case 3: temp = temp & 0xF8; temp1 = temp1 & 0x07; break; case 4: temp = temp & 0xF0; temp1 = temp1 & 0x0F; break; case 5: temp = temp & 0xE0; temp1 = temp1 & 0x1F; break; case 6: temp = temp & 0xC0; temp1 = temp1 & 0x3F; break; case 7: temp = temp & 0x80; temp1 = temp1 & 0x7F; break; default: break; } buffer[0] = temp; UID[row - 1] = temp1 | temp; for(i = 1; i < length; i++) { UID[row - 1 + i] = buffer[i]; } }}/****************************************************************//*名称: Set_BitFraming *//*功能: 该函数设置待发送数据的字节数*//*输入: row: 产生冲突的行*//* col: 产生冲突的列*//*输出: N/A *//****************************************************************/void Set_BitFraming(uchar row, uchar col){ switch(row) { case 0: buffer[1] = 0x20; break; case 1: buffer[1] = 0x30; break; case 2: buffer[1] = 0x40; break; case 3: buffer[1] = 0x50; break; case 4: buffer[1] = 0x60; break; default: break; } switch(col) { case 0: write_reg(0x0F,0x00); break; case 1: write_reg(0x0F,0x11); buffer[1] = (buffer[1] | 0x01); break; case 2: write_reg(0x0F,0x22); buffer[1] = (buffer[1] | 0x02); break; case 3: write_reg(0x0F,0x33); buffer[1] = (buffer[1] | 0x03); break; case 4: write_reg(0x0F,0x44); buffer[1] = (buffer[1] | 0x04); break; case 5: write_reg(0x0F,0x55); buffer[1] = (buffer[1] | 0x05); break; case 6: write_reg(0x0F,0x66); buffer[1] = (buffer[1] | 0x06); break; case 7: write_reg(0x0F,0x77); buffer[1] = (buffer[1] | 0x07); break; default: break; }}/****************************************************************//*名称: Rc531_Bus_Sel *//*功能: 该函数实现对RC531操作的总线方式(并行总线,SPI)选择 */ /* *//*输入: *//* N/A *//* *//*输出: *//* TRUE, 总线选择成功 *//* FALSE, 总线选择失败 *//****************************************************************/uchar FM1715_Bus_Sel(void){ uchar i,temp; write_reg(Page_Sel,0x80); for(i = 0; i < RF_TimeOut; i++) { temp=read_reg(Command); if(temp == 0x00) { write_reg(Page_Sel,0x00); return TRUE; } } return FALSE;}void Init_FM1715(void){ uint i,dat; MFRST = 1; //RC531复位 for (i = 0; i < 0x3fff; i++) { _nop_(); } MFRST = 0; for (i = 0; i < 0x3fff; i++) { _nop_(); } sck=0; dat=read_reg(0x01); while(dat!=0x00) dat=read_reg(0x01); FM1715_Bus_Sel(); //RC531总线选择}/****************************************************************//*名称: Command_Send *//*功能: 该函数实现向RC531发送命令集的功能 *//* *//*输入: *//* count, 待发送命令集的长度 *//* buff, 指向待发送数据的指针 *//* Comm_Set, 命令码 *//* *//*输出: *//* TRUE, 命令被正确执行 *//* FALSE, 命令执行错误 *//****************************************************************/uchar Command_Send(uchar count,uchar idata * buff,uchar Comm_Set){ uint j; uchar idata temp; write_reg(Command, 0x00); Clear_FIFO(); if (count != 0) { Write_FIFO(count, buff); } temp =read_reg(FIFO_Length); write_reg(Command, Comm_Set); //命令执行 for(j = 0; j< RF_TimeOut; j++) //检查命令执行否 { temp =read_reg(Command); if(temp == 0x00) { return TRUE; } } return FALSE; }#if 0/****************************************************************//*名称: Read_E2 *//*功能: 该函数实现从FM1715的EE中读出数据*//*输入: lsb, EE地址(低字节) *//* msb, EE地址(高字节) *//* count, 待读出数据EE的字节个数*//* buff, 指向待读出数据的指针*//*输出: TRUE, EE数据正确读出*//* FALSE, EE数据读出有误*//****************************************************************/uchar Read_E2(uchar lsb, uchar msb, uchar count, uchar idata *buff){ /*~~~~~~~~~*/ uchar temp; /*~~~~~~~~~*/ *buff = lsb; *(buff + 1) = msb; *(buff + 2) = count; temp = Command_Send(3, buff, ReadE2); Read_FIFO(buff); if(temp == FALSE) return(TRUE); return(FALSE);}/****************************************************************//*名称: Write_E2 *//*功能: 该函数实现向FM1715的EE中写入数据*//*输入: lsb, EE地址(低字节) *//* msb, EE地址(高字节) *//* count, 待写入数据EE的字节个数*//* buff, 指向待写入数据的指针*//*输出: TRUE, EE数据正确写入*//* FALSE, EE数据写入有误*//****************************************************************/uchar Write_E2(uchar lsb, uchar msb, uchar count, uchar idata *buff){ /*~~~~~~~~~~~~~~~~~~~~*/ uchar idata temp, i; /*~~~~~~~~~~~~~~~~~~~~*/ for(i = 0; i < count; i++) { *(buff + count - i + 2) = *(buff - i + count); } *buff = lsb; *(buff + 1) = msb; temp = Command_Send(count + 2, buff, WriteE2); temp = read_reg(0x05); temp = temp & 0x40; if(temp == 0x40) { return TRUE; } return FALSE;}#endif/****************************************************************//*名称: MIF_Halt *//*功能: 该函数实现暂停MIFARE卡*//*输入: N/A *//*输出: FM1715_OK: 应答正确*//* FM1715_PARITYERR: 奇偶校验错*//* FM1715_CRCERR: CRC校验错*//* FM1715_NOTAGERR: 无卡*//****************************************************************/uchar MIF_Halt(void){ /*~~~~~~~~~*/ uchar temp; uint i; /*~~~~~~~~~*/ write_reg(0x23,0x63); write_reg(0x12,0x3f); write_reg(0x22,0x07); //change by hbp 03-->07 *buffer = RF_CMD_HALT; *(buffer + 1) = 0x00; temp = Command_Send(2, buffer, Transmit); if(temp == TRUE) { for(i = 0; i < 0x50; i++) { _nop_(); } return FM1715_OK; } else { temp = read_reg(0x0A); if((temp & 0x02) == 0x02) { return(FM1715_PARITYERR); } if((temp & 0x04) == 0x04) { return(FM1715_FRAMINGERR); } return(FM1715_NOTAGERR); }}///////////////////////////////////////////////////////////////////////// 转换密钥格式///////////////////////////////////////////////////////////////////////char M500HostCodeKey(unsigned char *uncoded, unsigned char *coded) { char idata status = FM1715_OK; unsigned char idata cnt = 0; unsigned char idata ln = 0; unsigned char idata hn = 0; for (cnt = 0; cnt < 6; cnt++) { ln = uncoded[cnt] & 0x0F; hn = uncoded[cnt] >> 4; coded[cnt * 2 + 1] = (~ln << 4) | ln; coded[cnt * 2 ] = (~hn << 4) | hn; } return FM1715_OK;}/****************************************************************//*名称: Load_keyE2 *//*功能: 该函数实现把E2中密码存入FM1715的keybuffer中*//*输入: Secnr: EE起始地址*//*输出: True: 密钥装载成功*//* False: 密钥装载失败*//****************************************************************/uchar Load_keyE2_CPY(uchar *uncoded_keys){ uchar temp; unsigned char coded_keys[13]; M500HostCodeKey(uncoded_keys, coded_keys); temp = Command_Send(12, coded_keys, LoadKey); temp = read_reg(0x0A) & 0x40; if (temp == 0x40) { return FALSE; } return TRUE;}/****************************************************************//*名称: Request *//*功能: 该函数实现对放入RC531操作范围之内的卡片的Request操作 */ /* *//*输入: *//* mode: ALL(监测所以RC531操作范围之内的卡片) *//* STD(监测在RC531操作范围之内处于HALT状态的卡片) *//* *//*输出: *//* FM222_NOTAGERR: 无卡 *//* FM222_OK: 应答正确 *//* FM222_REQERR: 应答错误 *//****************************************************************/uchar Request(uchar mode){ uchar temp; write_reg(TxControl,0x58); delay1(1); write_reg(TxControl,0x5b); write_reg(CRCPresetLSB,0x63); write_reg(CWConductance,0x3f); buffer[0] = mode; //Request模式选择 write_reg(Bit_Frame,0x07); //发送7bit write_reg(ChannelRedundancy,0x03); //关闭CRC write_reg(TxControl,0x5b); write_reg(Control,0x01); //temp; //屏蔽CRYPTO1位 temp = Command_Send(1, buffer, Transceive); if(temp == FALSE) { return FM1715_NOTAGERR; } Read_FIFO(buffer); //从FIFO中读取应答信息 temp = Judge_Req(buffer); //判断应答信号是否正确 if (temp == TRUE) { tagtype[0] = buffer[0]; tagtype[1] = buffer[1]; return FM1715_OK; } return FM1715_REQERR;}/****************************************************************//*名称: AntiColl *//*功能: 该函数实现对放入FM1715操作范围之内的卡片的防冲突检测*//*输入: N/A *//*输出: FM1715_NOTAGERR: 无卡*//* FM1715_BYTECOUNTERR: 接收字节错误*//* FM1715_SERNRERR: 卡片序列号应答错误*//* FM1715_OK: 卡片应答正确*//****************************************************************/uchar AntiColl(void){ /*~~~~~~~~~~~~~*/ uchar temp; uchar i; uchar row, col; uchar pre_row; /*~~~~~~~~~~~~~*/ row = 0; col = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -