910 lines
25 KiB
C
910 lines
25 KiB
C
#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, ®_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, ®data );
|
||
|
||
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,®_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,®_data);//请勿修改
|
||
printf("0x24 = %02X\r\n",reg_data);
|
||
GetReg_Ext(0x25,®_data);//请勿修改
|
||
printf("0x25 = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDCTRLMODE,®_data);//场检测使能,场检测灵敏度0,LPCD使能
|
||
printf("JREG_LPCDCTRLMODE = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDSLEEPTIMER,®_data);//设置LPCD休眠阶段时间
|
||
printf("JREG_LPCDSLEEPTIMER = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDRFTIMER,®_data);//探测使用5us,LPCD探测总时间18us
|
||
printf("JREG_LPCDRFTIMER = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDTHRESH_L,®_data);//LPCD触发阈值低6位
|
||
printf("JREG_LPCDTHRESH_L = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDTHRESH_H, ®_data);//LPCD触发阈值高2位
|
||
printf("JREG_LPCDTHRESH_H = %02X\r\n",reg_data);
|
||
|
||
GetReg_Ext(JREG_LPCDTXCTRL2, ®_data);//设置LPCD输出P驱动
|
||
printf("JREG_LPCDTXCTRL2 = %02X\r\n",reg_data);
|
||
GetReg_Ext(JREG_LPCDTXCTRL3, ®_data);//设置LPCD输出N驱动
|
||
printf("JREG_LPCDTXCTRL3 = %02X\r\n",reg_data);
|
||
|
||
GetReg_Ext(JREG_LPCDREQATIMER,®_data);//REQA检测载波时间,5ms兼容手机方案
|
||
printf("JREG_LPCDREQATIMER = %02X\r\n",reg_data);
|
||
|
||
GetReg_Ext(JREG_LPCDREQAANA,®_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,®_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, ®);
|
||
GetReg_Ext(JREG_LPCDICURR_LO, ®1);
|
||
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, ®);
|
||
GetReg_Ext(JREG_LPCDQCURR_LO, ®1);
|
||
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, ®);
|
||
GetReg_Ext(JREG_LPCDILAST_LO, ®1);
|
||
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, ®);
|
||
GetReg_Ext(JREG_LPCDQLAST_LO, ®1);
|
||
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, ®);
|
||
GetReg_Ext(JREG_LPCDDELTA_LO, ®1);
|
||
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,®_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,®_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,®_data);
|
||
if(reg_data != 1)
|
||
{
|
||
//printf("SELECT ERROR\r\n");
|
||
return FAIL;
|
||
}
|
||
|
||
GetReg(JREG_ERROR,®_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,®_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,®_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,®_data);
|
||
|
||
if(reg_data == 16)
|
||
{
|
||
for(i=0;i<16;i++)
|
||
{
|
||
GetReg(0x09,&page_data[i]);
|
||
}
|
||
GetReg(0x06,®_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,®_data);
|
||
if(reg_data == 1)
|
||
{
|
||
GetReg(0x09,®_data);
|
||
if(encrypt == ENABLE)
|
||
{
|
||
PRINT_Calc_recvData(®_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,®_data);
|
||
if(reg_data == rece_length)
|
||
{
|
||
for(i=0;i<rece_length;i++)
|
||
{
|
||
GetReg(0x09,&rece_buff[i]);
|
||
}
|
||
GetReg(0x06,®_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;
|
||
}
|
||
|
||
}
|
||
|
||
|