Files
banban/ql-application/threadx/interface/custom_app/lib/libfm17622/READER.c
T

910 lines
25 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "READER.h"
#include "READER_REG.h"
#include "LPCD_CFG.h"
#include <stdio.h>
#include "ql_rtos.h"
#include "ql_application.h"
#include "ql_audio.h"
#include "ql_iic.h"
#include "ql_gpio.h"
#include "app_inc.h"
#include "ql_fs.h"
unsigned char fm17622_i2c_no = 1; //CI2C match to twsi1
unsigned char ATQA[2];
unsigned char UID[8];
unsigned char UID_SIZE;
unsigned char SAK[1];
void FM17622_WriteRawRC(uint8_t Address, uint8_t value)
{
ql_i2c_write(nfc_i2c_no, 0x50>>1, Address, &value, 1);
}
u8 DP1312EA_ReadRawRC(uint8_t Address)
{
u8 ucResult=0;
ql_i2c_read(nfc_i2c_no, 0x50>>1, Address, &ucResult, 1);
return ucResult;
}
void DelayUs( uint32_t xus )
{
int t;
while ( xus-- )
{
t = 5;
while ( t-- )
;
}
}
void DelayMs( uint32_t xms )
{
DelayUs( xms * 1000 );
}
unsigned char Reader_HardReset( void )
{
NPD_0; // NPD = 0
DelayMs( 1 );
NPD_1; // NPD = 1
DelayMs( 10 );
return (SUCCESS);
}
unsigned char Reader_SoftReset( void )
{
SetReg(JREG_COMMAND,CMD_SOFT_RESET);
DelayMs( 10 );
return (SUCCESS);
}
unsigned char Reader_Set_HPD( unsigned char mode ) //mode = DISABLE 退出HPD模式 ,mode = ENABLE 进入HPD模式
{
if ( mode == ENABLE )
{
DelayMs( 1 ); //延时1ms
NPD_0; // NPD = 0
}
else
{
NPD_1; // NPD = 1
DelayMs( 1 ); //延时1ms,等待Reader启动
}
return (mode);
}
void Reader_GPIO_Init( void )
{
LL_GPIO_SetPinMode( NPD_GPIO, NPD_PIN, LL_GPIO_PINxMODE_OUTPUT );
LL_GPIO_SetPinMode(IRQ_GPIO,IRQ_PIN,LL_GPIO_PINxMODE_INPUT );
LL_GPIO_SetPinMode( SDA_GPIO, SDA_PIN, LL_GPIO_PINxMODE_OUTPUT ); // PB0 Digital function - I2C SDA
LL_GPIO_EnablePinOpenDrain( SDA_GPIO, SDA_PIN );
LL_GPIO_EnablePinPullUp( SDA_GPIO, SDA_PIN );
LL_GPIO_SetPinMode( SCL_GPIO, SCL_PIN, LL_GPIO_PINxMODE_OUTPUT ); // PB2 Digital function - I2C SCL
LL_GPIO_EnablePinOpenDrain( SCL_GPIO, SCL_PIN );
LL_GPIO_EnablePinPullUp( SCL_GPIO, SCL_PIN );
SCL_1;
SDA_1;
NPD_0;
}
unsigned char GetReg( unsigned char reg_address, unsigned char *reg_data )
{
unsigned char i2c_address;
i2c_address = I2C_ADDRESS; //
u8 temp = 0;
u16 err = 255;
while ( temp == 0 ) //一直发送器件地址,直至唤醒器件为止
{
//1.开始
I2C_START();
//2.设备地址、写
temp = I2C_Write_Byte( (i2c_address << 1) & 0xfe );
if ( --err == 0 )
{
printf( "GetReg Error1\r\n" );
return (1);
}
}
//3.寄存器地址
temp = I2C_Write_Byte( reg_address );
if ( temp == 0 )
{
I2C_STOP();
printf( "GetReg Error2\r\n" );
return (0x2);
}
I2C_STOP();
//4.重新开始
temp = 0;
err = 255;
while ( temp == 0 )
{
I2C_START();
//5.设备地址、读
temp = I2C_Write_Byte( (i2c_address << 1) | (I2C_Read) );
if ( --err == 0 )
{
printf( "GetReg Error3\r\n" );
return (3);
}
}
//6.读一字节数据
*reg_data = I2C_Read_Byte( 0 );
//7.停止
I2C_STOP();
return (SUCCESS);
}
unsigned char SetReg( unsigned char reg_address, unsigned char reg_data )
{
unsigned char i2c_address;
i2c_address = I2C_ADDRESS; //
u8 temp = 0;
u16 err = 255;
while ( temp == 0 ) //一直发送器件地址,直至唤醒器件为止
{
//1.开始start
I2C_START();
//2.设备地址/写 //设备地址,EA=1,ADDR[6:0]=0xxxxxx,硬件定义;EA=0,0101XXX,低三位硬件定义
temp = I2C_Write_Byte( (i2c_address << 1) & 0xfe );
if ( --err == 0 )
{
printf( "SetReg Error1\r\n" );
return (1);
}
}
//3.数据地址
temp = I2C_Write_Byte( reg_address );
if ( temp == 0 )
{
I2C_STOP();
//printf("SetReg Error2\r\n");
return (0x2);
}
//4.写一字节数据
temp = I2C_Write_Byte( reg_data );
if ( temp == 0 )
{
I2C_STOP();
//printf("SetReg Error3\r\n");
return (0x3);
}
//5.停止
I2C_STOP();
I2C_DELAY( 2 );
return (SUCCESS);
}
//*******************************************************
//函数名称:ModifyReg(unsigned char addr,unsigned char* mask,unsigned char set)
//函数功能:写寄存器
//入口参数:addr:目标寄存器地址 mask:要改变的位
// set: 0:标志的位清零 其它:标志的位置起
//出口参数:
//********************************************************
void ModifyReg( unsigned char reg_address, unsigned char mask, unsigned char set )
{
unsigned char reg_data;
GetReg( reg_address, &reg_data );
if ( set )
{
reg_data |= mask;
}
else
{
reg_data &= ~mask;
}
SetReg( reg_address, reg_data );
return;
}
//***********************************************
//函数名称:GetReg_Ext(unsigned char ExtRegAddr,unsigned char* ExtRegData)
//函数功能:读取扩展寄存器值
//入口参数:ExtRegAddr:扩展寄存器地址 ExtRegData:读取的值
//出口参数:unsigned char TRUE:读取成功 FALSE:失败
//***********************************************
unsigned char GetReg_Ext( unsigned char ExtRegAddr, unsigned char* ExtRegData )
{
SetReg( JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_RD_ADDR | ExtRegAddr );
GetReg( JREG_EXT_REG_ENTRANCE, &(*ExtRegData) );
return (SUCCESS);
}
//***********************************************
//函数名称:SetReg_Ext(unsigned char ExtRegAddr,unsigned char* ExtRegData)
//函数功能:写扩展寄存器
//入口参数:ExtRegAddr:扩展寄存器地址 ExtRegData:要写入的值
//出口参数:unsigned char TRUE:写成功 FALSE:写失败
//***********************************************
unsigned char SetReg_Ext( unsigned char ExtRegAddr, unsigned char ExtRegData )
{
//unsigned char t = 0;
//GetReg_Ext( ExtRegAddr, &t );
//printf("1Get Ext reg %x, data %x\r\n", ExtRegAddr, t);
//printf("1Set Ext reg %x, data %x\r\n", ExtRegAddr, ExtRegData);
SetReg( JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_WR_ADDR | ExtRegAddr );
SetReg( JREG_EXT_REG_ENTRANCE, JBIT_EXT_REG_WR_DATA | ExtRegData );
//GetReg_Ext(ExtRegAddr, &t);
//printf("2Get Ext reg %x, data %x\r\n\r\n", ExtRegAddr, t);
return (SUCCESS);
}
//*******************************************************
//函数名称:ModifyReg_Ext(unsigned char ExtRegAddr,unsigned char* mask,unsigned char set)
//函数功能:寄存器位操作
//入口参数:ExtRegAddr:目标寄存器地址 mask:要改变的位
// set: 0:标志的位清零 其它:标志的位置起
//出口参数:unsigned char TRUE:写成功 FALSE:写失败
//********************************************************
void ModifyReg_Ext( unsigned char ExtRegAddr, unsigned char mask, unsigned char set )
{
unsigned char regdata;
GetReg_Ext( ExtRegAddr, &regdata );
if ( set )
{
regdata |= mask;
}
else
{
regdata &= ~(mask);
}
SetReg_Ext( ExtRegAddr, regdata );
return;
}
unsigned char Lpcd_Init_Register(void)
{
unsigned char reg_data;
SetReg(JREG_COMMAND,0x20);
GetReg(JREG_COMMAND,&reg_data);
printf("JREG_COMMAND = %02X\r\n",reg_data);
if(reg_data == 0x20)
{
SetReg_Ext(0x24, 0x14);//请勿修改
SetReg_Ext(0x25, 0x3A);//请勿修改
SetReg_Ext(JREG_LPCDCTRLMODE, (RF_DET_DISABLE|RF_DET_SEN_00|LPCD_ENABLE));//场检测使能,场检测灵敏度0,LPCD使能
SetReg_Ext(JREG_LPCDSLEEPTIMER, LPCD_SLEEPTIME);//设置LPCD休眠阶段时间
SetReg_Ext(JREG_LPCDRFTIMER, LPCD_IRQINV_ENABLE|LPCD_IRQ_PUSHPULL|LPCD_RFTIME_5us);//探测使用5us,LPCD探测总时间18us
SetReg_Ext(JREG_LPCDTHRESH_L, LPCD_THRSH & 0x3F);//LPCD触发阈值低6位
SetReg_Ext(JREG_LPCDTHRESH_H, BIT5|BIT2|((LPCD_THRSH & 0xC0)>>6));//LPCD触发阈值高2位
SetReg_Ext(JREG_LPCDTXCTRL2, LPCD_CWP);//设置LPCD输出P驱动
SetReg_Ext(JREG_LPCDTXCTRL3, LPCD_CWN);//设置LPCD输出N驱动
SetReg_Ext(JREG_LPCDREQATIMER,LPCD_REQA_TIME_5ms);//REQA检测载波时间,5ms兼容手机方案
SetReg_Ext(JREG_LPCDREQAANA,LPCD_RXGAIN_33DB | LPCD_MINLEVEL_9 | LPCD_MODWIDTH_38);//配置REQA检测命令的接收增益,接收阈值,调制宽度
//SetReg_Ext(JREG_LPCDDETECTMODE,LPCD_TXSCALE_4|LPCD_COMBINE_MODE);//配置REQA检测发射功率与探测输出场强的比例,LCPD探测模式设置
SetReg_Ext(JREG_LPCDDETECTMODE, LPCD_TXSCALE_4|LPCD_RX_CHANGE_MODE);
GetReg_Ext(0x24,&reg_data);//请勿修改
printf("0x24 = %02X\r\n",reg_data);
GetReg_Ext(0x25,&reg_data);//请勿修改
printf("0x25 = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDCTRLMODE,&reg_data);//场检测使能,场检测灵敏度0,LPCD使能
printf("JREG_LPCDCTRLMODE = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDSLEEPTIMER,&reg_data);//设置LPCD休眠阶段时间
printf("JREG_LPCDSLEEPTIMER = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDRFTIMER,&reg_data);//探测使用5us,LPCD探测总时间18us
printf("JREG_LPCDRFTIMER = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDTHRESH_L,&reg_data);//LPCD触发阈值低6位
printf("JREG_LPCDTHRESH_L = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDTHRESH_H, &reg_data);//LPCD触发阈值高2位
printf("JREG_LPCDTHRESH_H = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDTXCTRL2, &reg_data);//设置LPCD输出P驱动
printf("JREG_LPCDTXCTRL2 = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDTXCTRL3, &reg_data);//设置LPCD输出N驱动
printf("JREG_LPCDTXCTRL3 = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDREQATIMER,&reg_data);//REQA检测载波时间,5ms兼容手机方案
printf("JREG_LPCDREQATIMER = %02X\r\n",reg_data);
GetReg_Ext(JREG_LPCDREQAANA,&reg_data);//配置REQA检测命令的接收增益,接收阈值,调制宽度
printf("JREG_LPCDREQAANA = %02X\r\n",reg_data);
//SetReg_Ext(JREG_LPCDDETECTMODE,LPCD_TXSCALE_4|LPCD_COMBINE_MODE);//配置REQA检测发射功率与探测输出场强的比例,LCPD探测模式设置
GetReg_Ext(JREG_LPCDDETECTMODE,&reg_data);
printf("JREG_LPCDDETECTMODE = %02X\r\n",reg_data);
return SUCCESS;
}
else
return FAIL;
}
void Lpcd_Get_ADC_Value(void)
{
unsigned char reg,reg1;
unsigned char Current1,Current2;
{
GetReg_Ext(JREG_LPCDICURR_HI, &reg);
GetReg_Ext(JREG_LPCDICURR_LO, &reg1);
Current1 = (reg<<6) + reg1;
Current2 = ((reg<<6)>>8);
printf("-> LPCD I Current is:");printf("%02X",Current2);printf("%02X",Current1);printf("\r\n");
GetReg_Ext(JREG_LPCDQCURR_HI, &reg);
GetReg_Ext(JREG_LPCDQCURR_LO, &reg1);
Current1 = (reg<<6) + reg1;
Current2 = ((reg<<6)>>8);
printf("-> LPCD Q Current is:");printf("%02X",Current2);printf("%02X",Current1);printf("\r\n");
GetReg_Ext(JREG_LPCDILAST_HI, &reg);
GetReg_Ext(JREG_LPCDILAST_LO, &reg1);
Current1 = (reg<<6) + reg1;
Current2 = ((reg<<6)>>8);
printf("-> LPCD I Last is:");printf("%02X",Current2);printf("%02X",Current1);printf("\r\n");
GetReg_Ext(JREG_LPCDQLAST_HI, &reg);
GetReg_Ext(JREG_LPCDQLAST_LO, &reg1);
Current1 = (reg<<6) + reg1;
Current2 = ((reg<<6)>>8);
printf("-> LPCD Q Last is:");printf("%02X",Current2);printf("%02X",Current1);printf("\r\n");
GetReg_Ext(JREG_LPCDDELTA_HI, &reg);
GetReg_Ext(JREG_LPCDDELTA_LO, &reg1);
Current1 = (reg<<6) + reg1;
Current2 = ((reg<<6)>>8);
printf("-> LPCD Delta is:");printf("%02X",Current2);printf("%02X",Current1);printf("\r\n");
}
return;
}
void Lpcd_IRQ_Event(void)
{
unsigned char irq;
Reader_Set_HPD(DISABLE); //NPD = 1,17611退出休眠模式
printf("-> LPCD Detceted!\r\n");
GetReg_Ext(JREG_LPCDIRQ, &irq);//读取LPCD中断标志
SetReg_Ext(JREG_LPCDIRQ, irq);//CLEAR LPCD IRQ
printf("IRQ = %02X\r\n",irq);
if(irq & 0x08)
{
printf("-> LPCD IRQ RFDET SET!\r\n");
}
if(irq & 0x04)
{
printf("-> LPCD IRQ RXCHANGE SET!\r\n");//LPCD中断标志
Lpcd_Get_ADC_Value();//用于LPCD功能调试
}
if(irq & 0x02)
{
printf("-> LPCD IRQ ATQAREC SET!\r\n");
}
Reader_SoftReset();
if((irq & 0x08) ||(irq & 0x04)||(irq & 0x02))
{
Lpcd_Card_Event();//卡片操作处理流程
}
Lpcd_Init_Register();//LPCD初始化
Reader_Set_HPD(ENABLE);//返回LPCD模式
printf("-> LPCD ENABLE!\r\n");
return;
}
unsigned int Reader_ADC(void)
{
u8 AdcQuad_H,AdcQuad_M,AdcQuad_L;
unsigned int AdcQuad;
ModifyReg_Ext(JREG_LPCDTEST,BIT5,SET);
DelayUs(30);
GetReg_Ext(JREG_LpcdQuad_H , &AdcQuad_H);
AdcQuad_H = AdcQuad_H & 0x3F;
GetReg_Ext(JREG_LpcdQuad_M , &AdcQuad_M);
AdcQuad_M = AdcQuad_M & 0x3F;
GetReg_Ext(JREG_LpcdQuad_L , &AdcQuad_L);
AdcQuad_L = AdcQuad_L & 0x3F;
AdcQuad = (AdcQuad_H<<12)|(AdcQuad_M<<6)|AdcQuad_L;
return AdcQuad;
}
unsigned char ReaderA_CW(unsigned char mode)
{
if(mode == ENABLE)
{
SetReg(JREG_TXCONTROL,0x83);//CW ON
}
else
{
SetReg(JREG_TXCONTROL,0x80);//CW OFF
}
DelayMs(5);
return SUCCESS;
}
unsigned char ReaderA_Initial(void)
{
SetReg(JREG_MODWIDTH,0x26); //MODWIDTH = 106kbps
SetReg(JREG_TXAUTO,0x40);//Force 100ASK = 1
SetReg(JREG_GSN,CWN<<4);//Config GSN; Config ModGSN
SetReg(JREG_CWGSP,CWP);//Config GSP
SetReg(JREG_CONTROL,0x10);//Initiator = 1
SetReg(JREG_RFCFG,RX_GAIN<<4);//Config RxGain
SetReg(JREG_RXTRESHOLD,(RX_MINLEVEL<<4)|RX_COLLLEVEL);//Config MinLevel; Config CollLevel
return SUCCESS;
}
unsigned char ReaderA_Request(unsigned char *atqa)
{
unsigned char reg_data;
SetReg(JREG_TXMODE,0);//Disable TxCRC
SetReg(JREG_RXMODE,0);//Disable RxCRC
SetReg(JREG_COMMAND,0x00);//command = Idel
SetReg(JREG_FIFOLEVEL,0x80);//Clear FIFO
SetReg(JREG_FIFODATA,0x26);
SetReg(JREG_COMMAND,0x0C);//command = Transceive
SetReg(JREG_BITFRAMING,0x87);//Start Send
DelayUs(500);//
GetReg(JREG_FIFOLEVEL,&reg_data);
if(reg_data == 2)
{
GetReg(JREG_FIFODATA,&atqa[0]);
GetReg(JREG_FIFODATA,&atqa[1]);
//if((atqa[0]==0x44)&&(atqa[1]==0x00))//可以增加卡片类型判断
{
return SUCCESS;
}
}
return FAIL;
}
unsigned char ReaderA_Anticol(unsigned char cmd,unsigned char *uid)
{
unsigned char reg_data;
SetReg(JREG_TXMODE,0x00);//Disable TxCRC
SetReg(JREG_RXMODE,0x00);//Disable RxCRC
SetReg(JREG_COMMAND,0x00);//command = Idel
SetReg(JREG_FIFOLEVEL,0x80);//Clear FIFO
SetReg(JREG_FIFODATA,cmd);
SetReg(JREG_FIFODATA,0x20);
SetReg(JREG_COMMAND,0x0C);//command = Transceive
SetReg(JREG_BITFRAMING,0x80);//Start Send
DelayUs(1000);//实测时间us
GetReg(JREG_FIFOLEVEL,&reg_data);
if(reg_data != 5)
{
//printf("ANTICOLL ERROR\r\n");
return FAIL;
}
GetReg(JREG_FIFODATA,&uid[0]);
GetReg(JREG_FIFODATA,&uid[1]);
GetReg(JREG_FIFODATA,&uid[2]);
GetReg(JREG_FIFODATA,&uid[3]);
GetReg(JREG_FIFODATA,&uid[4]);
if((uid[0]^uid[1]^uid[2]^uid[3]) != uid[4])
{
return FAIL;
}
return SUCCESS;
}
unsigned char ReaderA_Select(unsigned char cmd,unsigned char *uid,unsigned char *sak)
{
unsigned char reg_data;
SetReg(JREG_TXMODE,0x80);//Enable TxCRC
SetReg(JREG_RXMODE,0x80);//Enable RxCRC
SetReg(JREG_COMMAND,0x00);//command = Idel
SetReg(JREG_FIFOLEVEL,0x80);//Clear FIFO
SetReg(JREG_FIFODATA,cmd);
SetReg(JREG_FIFODATA,0x70);
SetReg(JREG_FIFODATA,uid[0]);
SetReg(JREG_FIFODATA,uid[1]);
SetReg(JREG_FIFODATA,uid[2]);
SetReg(JREG_FIFODATA,uid[3]);
SetReg(JREG_FIFODATA,uid[4]);
SetReg(JREG_COMMAND,0x0C);//command = Transceive
SetReg(JREG_BITFRAMING,0x80);//Start Send
DelayUs(1100);//
GetReg(JREG_FIFOLEVEL,&reg_data);
if(reg_data != 1)
{
//printf("SELECT ERROR\r\n");
return FAIL;
}
GetReg(JREG_ERROR,&reg_data);//判断错误寄存器
if(reg_data != 0)
{
return FAIL;
}
GetReg(JREG_FIFODATA,&*sak);
return SUCCESS;
}
unsigned char Lpcd_Card_Event(void)
{
unsigned char result;
ReaderA_Initial(); //TYPE A 初始化
ReaderA_CW(ENABLE); //打开载波输出
UID_SIZE = 8;
memset(UID,0,UID_SIZE);//UID初始化为0
result = ReaderA_Request(ATQA);
if(result != SUCCESS)
{
ReaderA_CW(DISABLE);
//printf("REQA_ERROR\r\n");
return FAIL;
}
//printf( "ATQA%02X = %02X%02X\r\n",READER_NUM,ATQA[num][0], ATQA[num][1]); //打印ATQA数据
result = ReaderA_Anticol(0x93,UID);
if(result != SUCCESS)
{
memset(UID,0,UID_SIZE);//清除错误的UID
ReaderA_CW(DISABLE);
//printf("ReaderA_Anticol_ERROR\r\n");
return FAIL;
}
result = ReaderA_Select(0x93,UID,SAK);
if(result != SUCCESS)
{
memset(UID,0,UID_SIZE);//清除错误的UID
ReaderA_CW(DISABLE);
//printf("ReaderA_Select_ERROR\r\n");
return FAIL;
}
//printf( "SAK%02X = %02X\r\n",READER_NUM,SAK[num][0]);//打印SAK数据
if(UID[0]!= 0x88)
{
UID_SIZE = 4;
printf("-> ATQA = %02X%02X\r\n",ATQA[0],ATQA[1]);
printf("-> UID = %02X%02X%02X%02X\r\n",UID[0],UID[1],UID[2],UID[3]);
printf("-> SAK = %02X\r\n",SAK[0]);
//此处添加用户卡片操作函数
//MIFARE_EVENT();
//用户卡片操作函数结束
ReaderA_CW(DISABLE); //关闭载波输出
return result;
}
else
{
UID_SIZE = 8;
}
result = ReaderA_Anticol(0x95,UID+4);
if(result != SUCCESS)
{
memset(UID,0,UID_SIZE);//清除错误的UID
ReaderA_CW(DISABLE);
//printf("ReaderA_Anticol_ERROR\r\n");
return FAIL;
}
result = ReaderA_Select(0x95,UID+4,SAK);
if(result != SUCCESS)
{
memset(UID,0,UID_SIZE);//清除错误的UID
ReaderA_CW(DISABLE);
//printf("ReaderA_Select_ERROR\r\n");
return FAIL;
}
printf("-> ATQA = %02X%02X\r\n",ATQA[0],ATQA[1]);
printf("-> UID = %02X%02X%02X%02X%02X%02X%02X%02X\r\n",UID[0],UID[1],UID[2],UID[3],UID[4],UID[5],UID[6],UID[7]);
printf("-> SAK = %02X\r\n",SAK[0]);
//此处添加用户卡片操作函数
//NTAG_EVENT();
//用户卡片操作函数结束
return result;
}
unsigned char FastRead_Page(unsigned char page_num1,unsigned char page_num2,unsigned char *page_data,unsigned char encrypt)
{
unsigned char reg_data,i,send_data[3],length;
SetReg(0x12,0x80);//Enable TxCRC
SetReg(0x13,0x80);//Enable RxCRC
SetReg(0x01,0x00);//command = Idel
SetReg(0x0A,0x80);//Clear FIFO
send_data[0] = 0x3A;
send_data[1] = page_num1;
send_data[2] = page_num2;
if(encrypt == ENABLE )
{
PRINT_Calc_sendData(send_data,3);
}
SetReg(0x09,send_data[0]);
SetReg(0x09,send_data[1]);
SetReg(0x09,send_data[2]);
SetReg(0x01,0x0C);//command = Transceive
SetReg(0x0D,0x80);//Start Send
DelayUs(3000);//实测时间us
GetReg(0x0A,&reg_data);
//printf("fastreadpage rece_length = %X \r\n",reg_data);
length = (page_num2-page_num1+1)*4;
if(reg_data == length)
{
for(i=0;i<length;i++)
{
GetReg(0x09,&page_data[i]);
}
GetReg(0x06,&reg_data);
if((reg_data&0x0F)==0)
{
if(encrypt == ENABLE)
{
//printf("Crypto_data = %02X%02X%02X%02X\r\n",page_data[0],page_data[1],page_data[2],page_data[3]);
PRINT_Calc_recvData(page_data,length);
}
return SUCCESS;
}
}
return FAIL;
}
unsigned char Read_Page(unsigned char page_num,unsigned char *page_data,unsigned char encrypt)
{
unsigned char reg_data,i,send_data[2];
SetReg(0x12,0x80);//Enable TxCRC
SetReg(0x13,0x80);//Enable RxCRC
SetReg(0x01,0x00);//command = Idel
SetReg(0x0A,0x80);//Clear FIFO
send_data[0] = 0x30;
send_data[1] = page_num;
if(encrypt == ENABLE )
{
PRINT_Calc_sendData(send_data,2);
}
SetReg(0x09,send_data[0]);
SetReg(0x09,send_data[1]);
SetReg(0x01,0x0C);//command = Transceive
SetReg(0x0D,0x80);//Start Send
DelayUs(2300);//实测时间2255us
GetReg(0x0A,&reg_data);
if(reg_data == 16)
{
for(i=0;i<16;i++)
{
GetReg(0x09,&page_data[i]);
}
GetReg(0x06,&reg_data);
if((reg_data&0x0F)==0)
{
if(encrypt == ENABLE)
{
//printf("Crypto_data = %02X%02X%02X%02X\r\n",page_data[0],page_data[1],page_data[2],page_data[3]);
PRINT_Calc_recvData(page_data,16);
}
return SUCCESS;
}
}
return FAIL;
}
unsigned char Write_Page(unsigned char page_num,unsigned char *page_data,unsigned char encrypt)
{
unsigned char reg_data,send_data[6];
SetReg(0x12,0x80);//Enable TxCRC
SetReg(0x13,0x00);//Enable RxCRC
SetReg(0x01,0x00);//command = Idel
SetReg(0x0A,0x80);//Clear FIFO
send_data[0] = 0xA2;
send_data[1] = page_num;
send_data[2] = page_data[0];
send_data[3] = page_data[1];
send_data[4] = page_data[2];
send_data[5] = page_data[3];
if(encrypt == ENABLE )
{
PRINT_Calc_sendData(send_data,6);
}
SetReg(0x09,send_data[0]);
SetReg(0x09,send_data[1]);
SetReg(0x09,send_data[2]);
SetReg(0x09,send_data[3]);
SetReg(0x09,send_data[4]);
SetReg(0x09,send_data[5]);
SetReg(0x01,0x0C);//command = Transceive
SetReg(0x0D,0x80);//Start Send
DelayMs(5);//5ms
GetReg(0x0A,&reg_data);
if(reg_data == 1)
{
GetReg(0x09,&reg_data);
if(encrypt == ENABLE)
{
PRINT_Calc_recvData(&reg_data,1);
}
if(reg_data != 0x0A)
return FAIL;
}
return SUCCESS;
}
unsigned char TPDU(unsigned char send_length,unsigned char *send_buff,unsigned char rece_length,unsigned char *rece_buff,unsigned int wait_time)
{
unsigned char i,reg_data;
//SetReg(0x12,0x80);//Enable TxCRC
//SetReg(0x13,0x80);//Enable RxCRC
SetReg(0x01,0x00);//command = Idel
SetReg(0x0A,0x80);//Clear FIFO
for(i = 0;i < send_length;i++)
{
SetReg(0x09,send_buff[i]);
}
SetReg(0x01,0x0C);//command = Transceive
SetReg(0x0D,0x80);//Start Send
DelayUs(wait_time);//
GetReg(0x0A,&reg_data);
if(reg_data == rece_length)
{
for(i=0;i<rece_length;i++)
{
GetReg(0x09,&rece_buff[i]);
}
GetReg(0x06,&reg_data);
if((reg_data&0x0F)==0)
{
return SUCCESS;
}
//printf("TPDU ERROR = %X \r\n",reg_data);
}
else
{
//printf("rece_length = %X \r\n",reg_data);
}
return FAIL;
}
unsigned char Triple_Auth(unsigned char *key,unsigned char *PCD_random)
{ //整个流程发送和接收CRC都打开
unsigned char result,i;
unsigned char PICC_random[2]={0x00,0x00};
unsigned char PICC_PCD_random[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char Token1[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char Token2[6] = {0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char rece_buff[6];
unsigned char send_buff[6];
unsigned long random_data;
send_buff[0] = 0xB3;
result = TPDU(1,send_buff,2,PICC_random,6500);
if(result != SUCCESS)
{
printf("TPDU1 ERROR\r\n");
return result;
}
for(i = 0;i < 2;i++)
{
PICC_PCD_random[i] = PICC_random[1-i];//PICC_random倒序
}
//printf("PCD_random = %2X%02X%02X%02X\r\n",PCD_random[0],PCD_random[1],PCD_random[2],PCD_random[3]);
random_data = Get_RandomNumber();
for(i = 0;i < 4;i++)
{
PICC_PCD_random[2+i] = random_data>>(i*8);
}
//printf("PICC_PCD_random = %02X%02X%02X%02X%02X%02X\r\n",PICC_PCD_random[0],PICC_PCD_random[1],PICC_PCD_random[2],PICC_PCD_random[3],PICC_PCD_random[4],PICC_PCD_random[5]);
Print_AUTH(key,PICC_PCD_random,rece_buff);//print认证
for(i=0;i<6;i++)
{
Token1[i] = rece_buff[5-i];//倒序
}
//authstat = AUTH_STAT_1;
result = TPDU(6,Token1,6,rece_buff,6000);
if(result != SUCCESS)
{
printf("TPDU2 ERROR\r\n");
return result;
}
for(i=0;i<6;i++)
{
Token2[i] = rece_buff[5-i];//倒序
}
//printf("Token2 = %2X%02X%02X%02X%02X%02X\r\n",Token2[0],Token2[1],Token2[2],Token2[3],Token2[4],Token2[5]);
Print_AUTH(key,Token2,rece_buff);//将Token2 print解密,前四个字节和PCD_random对比,对比成功说明认证成功
//printf("rece_buff = %02X%02X%02X%02X%02X%02X\r\n",rece_buff[0],rece_buff[1],rece_buff[2],rece_buff[3],rece_buff[4],rece_buff[5]);
for(i = 0;i < 4;i++)
{
PICC_PCD_random[2+i] = random_data>>(i*8);
}
//printf("PICC_PCD_random = %02X%02X%02X%02X%02X%02X\r\n",PICC_PCD_random[0],PICC_PCD_random[1],PICC_PCD_random[2],PICC_PCD_random[3],PICC_PCD_random[4],PICC_PCD_random[5]);
if(memcmp(rece_buff,PICC_PCD_random+2,4))
{
return FAIL;
}
else
{
lsfr_init(rece_buff);//初始化密码流为之后的读写认证准备
return SUCCESS;
}
}