📄 zlg500.c
字号:
#include <string.h>
#include "Zlg500.h"
#include "zlg500Commu.h"
// 命令类型
enum CommandType
{
CT_CTRL_DEV = 1, // 设备控制类
CT_CTRL_14443A = 2 // ISO14443A类
};
// 设备控制类命令(对读卡设备)
enum ControlDeviceCommand
{
CDC_GET_DEV_INFO = 'A', // 获取设备信息
CDC_CONFIG_CHIP = 'B', // 配置读卡芯片
CDC_CLOSE_CHIP = 'C', // 关闭读卡芯片
CDC_LOAD_KEY = 'E', // 装载密钥
CDC_WRITE_REG = 'F', // 写读卡芯片寄存器
CDC_READ_REG = 'G' // 读读卡芯片寄存器
};
// ISO14443A类命令(对卡)
enum ISO14443ACommand
{
ISOAC_REQUEST = 'A', // 请求
ISOAC_ANTICOLL = 'B', // 防碰撞
ISOAC_SELECT = 'C', // 选择
ISOAC_HALT = 'D', // 挂失
ISOAC_AUTH_KEY_E2PROM = 'E', // 用E2PROM的密钥来验证实
ISOAC_AUTH_KEY = 'F', // 直接密钥验证
ISOAC_READ_BLOCK = 'G', // 读数据块
ISOAC_WRITE_BLOCK = 'H', // 写数据块
ISOAC_UL_WRITE_BLOCK = 'I', // 写UltraLight卡的数据块
ISOAC_OP_VALUE = 'J', // 值操作
ISOAC_CLOSE_ANT = 'L', // 关闭天线
ISOAC_ACTIVE_TYPE_A = 'M', // 激活A型卡
ISOAC_AUTO_DETECT = 'N', // 设置自动检测卡
ISOAC_READ_DETECT_DATA = 'O' // 读自动检测数据
};
///////////////////////////////////////////////////////////////////////////////
// 读卡模块控制函数
//
// 初始化与读卡模块的通信
uint8 PCD_Init(void)
{
return ZLG500_COM_Init();
}
// 获取读卡模块的描述信息
#if PCD_GET_DEV_INFO_EN
uint8 PCD_GetDevInfo(char *pDevInfo, uint8 nInfoSize)
{
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_GET_DEV_INFO, NULL, 0, pDevInfo, nInfoSize);
}
#endif // PCD_GET_DEV_INFO_EN
// 配置读卡模块,配置后默认为ISO14443A方式。
#if PCD_CONFIG_EN
uint8 PCD_Config(void)
{
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_CONFIG_CHIP, NULL, 0, NULL, 0);
}
#endif // PCD_CONFIG_EN
// 关闭读卡芯片。
#if PCD_CLOSE_EN
uint8 PCD_Close(void)
{
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_CLOSE_CHIP, NULL, 0, NULL, 0);
}
#endif // PCD_CLOSE_EN
// 装载密钥到读卡模块
#if PCD_LOAD_KEY_EN
uint8 PCD_LoadKey(uint8 nSectorNumber, uint8 nKeyType, const uint8 *pKey)
{
uint8 buf[8];
buf[0] = nKeyType;
buf[1] = nSectorNumber;
memcpy(&buf[2], pKey, 6);
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_LOAD_KEY, buf, 8, NULL, 0);
}
#endif // PCD_LOAD_KEY_EN
// 写读卡芯片的寄存器
uint8 PCD_WriteReg(uint8 nRegAddr, uint8 nRegValue)
{
uint8 buf[2];
buf[0] = nRegAddr;
buf[1] = nRegValue;
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_WRITE_REG, buf, 2, NULL, 0);
}
// 读读卡芯片的寄存器
#if 0 // 一般不需使用此函数
uint8 PCD_ReadReg(uint8 nRegAddr, uint8 *pRegValue)
{
return ZLG500_COM_SendReceive(CT_CTRL_DEV, CDC_READ_REG,
&nRegAddr, sizeof(nRegAddr),
pRegValue, sizeof(*pRegValue));
}
#endif // 0
// 选择天线的输出方式,可同时选择两个天线输出。
#if PCD_SEL_ANT_EN
uint8 PCD_SelectAntennaTx(uint8 bEnableTx1, uint8 bEnableTx2)
{
// 地址为0x11的寄存器的0 bit和1 bit分别控制天线1和天线2的开关
uint8 nValue = 0x58;
if (bEnableTx1)
{
nValue |= 1 << 0;
}
if (bEnableTx2)
{
nValue |= 1 << 1;
}
return PCD_WriteReg(0x11, nValue);
}
#endif // PCD_SEL_ANT_EN
// 关闭天线。
#if PCD_CLOSE_ANT_EN
uint8 PCD_CloseAntennaTx(uint8 nCloseTime)
{
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_CLOSE_ANT, &nCloseTime, 1, NULL, 0);
}
#endif // PCD_CLOSE_ANT_EN
///////////////////////////////////////////////////////////////////////////////
// ISO14443A命令函数
//
// 请求卡片
#if PICC_REQUEST_EN
uint8 PICC_Request(uint8 nRequestMode, uint16 *pCardType)
{
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_REQUEST,
&nRequestMode, sizeof(nRequestMode),
pCardType, sizeof(*pCardType));
}
#endif // PICC_REQUEST_EN
// 防碰撞。
#if PICC_ANTICOLL_EN
uint8 PICC_Anticoll(uint8 nSelectCode, uint32 *pCardSN)
{
uint8 nBitCount = 0;
uint8 buf[2];
buf[0] = nSelectCode;
buf[1] = nBitCount;
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_ANTICOLL,
buf, sizeof(buf),
pCardSN, sizeof(*pCardSN));
}
#endif // PICC_ANTICOLL_EN
// 选择卡片。
#if PICC_SELECT_EN
uint8 PICC_Select(uint8 nSelectCode, uint32 nCardSN, uint8 *pSAK)
{
uint8 buf[5];
buf[0] = nSelectCode;
memcpy(&buf[1], &nCardSN, sizeof(nCardSN));
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_SELECT,
buf, sizeof(buf),
pSAK, sizeof(*pSAK));
}
#endif // PICC_SELECT_EN
// 激活A型卡,此操作是卡片请求、防碰撞和选择三个步骤的综合。
#if PICC_ACTIVE_TYPEA_EN
uint8 PICC_ActiveTypeA(uint8 nRequestCode, uint16 *pCardType, uint32 *pCardSN)
{
uint8 nBaudrate = 0;
uint8 nStatus;
uint8 sendBuf[2];
uint8 receiveBuf[12];
sendBuf[0] = nBaudrate;
sendBuf[1] = nRequestCode;
nStatus = ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_ACTIVE_TYPE_A, sendBuf, 2, receiveBuf, sizeof(receiveBuf));
if (nStatus == OK)
{
memcpy(pCardType, &receiveBuf[0], sizeof(*pCardType));
// *pATS = receiveBuf[2];
// *pCardSNLen = receiveBuf[3];
memcpy(pCardSN, &receiveBuf[4], 4);
}
return nStatus;
}
#endif // PICC_ACTIVE_TYPEA_EN
// 将之前选择的卡片挂起。
#if PICC_HALT_EN
uint8 PICC_Halt()
{
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_HALT, NULL, 0, NULL, 0);
}
#endif // PICC_HALT_EN
// 通过保存在读卡模块E2PEOM的密钥来验证相应的卡块。
#if PICC_AUTH_KEY_E2PROM_EN
uint8 PICC_AuthKeyE2PROM(uint8 nSectorNumber, uint8 nKeyType, uint32 nCardSN, uint8 nBlockNumber)
{
uint8 buf[7];
buf[0] = nKeyType;
memcpy(&buf[1], &nCardSN, sizeof(nCardSN));
buf[5] = nSectorNumber;
buf[6] = nBlockNumber;
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_AUTH_KEY_E2PROM, buf, 7, NULL, 0);
}
#endif // PICC_AUTH_KEY_E2PROM_EN
// 使用直接密钥来验证相应的卡块。
#if PICC_AUTH_KEY_EN
uint8 PICC_AuthKeyDirect(const uint8 *pKey, uint8 nKeyType, uint32 nCardSN,uint8 nBlockNumber)
{
uint8 buf[12];
buf[0] = nKeyType;
memcpy(&buf[1], &nCardSN, sizeof(nCardSN));
memcpy(&buf[5], pKey, 6);
buf[11] = nBlockNumber;
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_AUTH_KEY, buf, 12, NULL, 0);
}
#endif // PICC_AUTH_KEY_EN
// 读卡片数据块,一块数据的大小为16字节。
#if PICC_READ_BLOCK_EN
uint8 PICC_ReadBlock(uint8 nBlockNumber, uint8 *pBlockData)
{
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_READ_BLOCK,
&nBlockNumber, sizeof(nBlockNumber),
pBlockData, 16);
}
#endif // PICC_AUTH_KEY_EN
// 写数据到卡片指定的块,一块数据的大小为16字节。
#if PICC_WRITE_BLOCK_EN
uint8 PICC_WriteBlock(uint8 nBlockNumber, const uint8 *pBlockData)
{
uint8 buf[17];
buf[0] = nBlockNumber;
memcpy(&buf[1], pBlockData, 16);
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_WRITE_BLOCK, buf, 17, NULL, 0);
}
#endif // PICC_WRITE_BLOCK_EN
// 读Ultralight卡片数据块,一块数据的大小为4字节。
#if PICC_UL_READ_BLOCK_EN
uint8 PICC_ULReadBlock(uint8 nBlockNumber, uint8 *pBlockData)
{
uint8 buf[16];
uint8 nStatus = PICC_ReadBlock(nBlockNumber, buf);
if (nStatus == OK)
{
memcpy(pBlockData, buf, 4);
}
return nStatus;
}
#endif // PICC_UL_READ_BLOCK_EN
// 写数据到Ultralight卡片指定的块,一块数据的大小为4字节。
#if PICC_UL_WRITE_BLOCK_EN
uint8 PICC_ULWriteBlock(uint8 nBlockNumber, const uint8 *pBlockData)
{
uint8 buf[5];
buf[0] = nBlockNumber;
memcpy(&buf[1], pBlockData, 4);
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_UL_WRITE_BLOCK, buf, 5, NULL, 0);
}
#endif // PICC_UL_WRITE_BLOCK_EN
// 读取卡片内指定的块的数值,数值为32位有符号数,一块只能存放
// 一个数值,有固定的存放格式,具体请参考Mifare 1的数据手册。
#if PICC_READ_VALUE_EN
uint8 PICC_ReadValue(int32 *pValue, uint8 nBlockNumber)
{
uint8 buf[16];
int32 nValue1, nValue2, nValue3;
uint8 nStatus = PICC_ReadBlock(nBlockNumber, buf);
if (nStatus == OK)
{
memcpy(&nValue1, &buf[0], 4);
memcpy(&nValue2, &buf[4], 4);
memcpy(&nValue3, &buf[8], 4);
if (nValue1 != ~nValue2 || nValue1 != nValue3)
{
return (uint8) -1;
}
*pValue = nValue1;
if (buf[12] != (uint8) ~buf[13] || buf[12] != buf[14] || buf[12] != (uint8) ~buf[15])
{
return (uint8) -1;
}
}
return nStatus;
}
#endif // PICC_READ_VALUE_EN
// 写数值到卡片,一块只能存放一个数值。
#if PICC_WRITE_VALUE_EN
uint8 PICC_WriteValue(int32 nValue, uint8 nBlockNumber)
{
uint8 buf[16];
// 数值:原值--取反--原值
int32 nInvertValue = ~nValue;
memcpy(&buf[0], &nValue, 4);
memcpy(&buf[4], &nInvertValue, 4);
memcpy(&buf[8], &nValue, 4);
// 地址:原值--取反--原值--取反
buf[12] = nBlockNumber;
buf[13] = ~nBlockNumber;
buf[14] = nBlockNumber;
buf[15] = ~nBlockNumber;
return PICC_WriteBlock(nBlockNumber, buf);
}
#endif // PICC_WRITE_VALUE_EN
// 操作数值。
#if PICC_OPERATE_VALUE_EN
uint8 PICC_OperateValue(uint8 nOperationMode, int32 nValue, uint8 nSourceBlockNumber, uint8 nDestBlockNumber)
{
uint8 buf[7];
buf[0] = nOperationMode;
buf[1] = nSourceBlockNumber;
memcpy(&buf[2], &nValue, 4);
buf[6] = nDestBlockNumber;
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_OP_VALUE, buf, 7, NULL, 0);
}
#endif // PICC_OPERATE_VALUE_EN
// 设置自动检测卡片的参数。
#if PICC_AUTO_DETECT_EN
uint8 PICC_AutoDetect(uint8 nOutMode, uint8 nTxMode, uint8 nRequestMode, uint8 nAuthMode,
uint8 nKeyType, const uint8 *pKey, uint8 nSectorNumber, uint8 nBlockNumber)
{
uint8 buf[12];
uint8 nInfoLen = 0;
buf[0] = nOutMode;
buf[1] = nTxMode;
buf[2] = nRequestMode;
buf[3] = nAuthMode;
switch (nAuthMode)
{
case 0:
nInfoLen = 4;
break;
case 'E':
nInfoLen = 7;
buf[4] = nKeyType;
buf[5] = nSectorNumber;
buf[6] = nBlockNumber;
break;
case 'F':
nInfoLen = 12;
buf[4] = nKeyType;
memcpy(&buf[5], pKey, 6);
buf[11] = nBlockNumber;
break;
default:
return COMM_ERR;
}
return ZLG500_COM_SendReceive(CT_CTRL_14443A, ISOAC_AUTO_DETECT, buf, nInfoLen, NULL, 0);
}
#endif // PICC_AUTO_DETECT_EN
// 接收模块自动检测到卡片主动发送上来的数据。
#if PICC_RECV_DETECT_DATA_EN
uint8 PICC_ReceiveDetectData(uint8 *pTxNumber, uint16 *pCardType, uint32 *pCardSN, uint8 *pBlockData)
{
uint8 bResult;
uint8 nCommType;
uint8 nStatus;
uint8 nRecvLen;
uint8 buf[30];
bResult = ZLG500_COM_Receive(&nCommType, &nStatus, buf, sizeof(buf), &nRecvLen);
if (!bResult)
{
return COMM_ERR;
}
*pTxNumber = buf[0];
memcpy(pCardType, &buf[1], 2);
// *pSAK = buf[3];
memcpy(pCardSN, &buf[5], 4);
if (pBlockData != NULL)
{
memcpy(pBlockData, &buf[5 + buf[4]], 16);
}
return nStatus;
}
#endif // PICC_RECV_DETECT_DATA_EN
// 读取模块自动检测到卡片的数据。
#if PICC_READ_DETECT_DATA_EN
uint8 PICC_ReadDetectData(uint8 nDetectMode, uint8 *pTxNumber, uint16 *pCardType, uint32 *pCardSN, uint8 *pBlockData)
{
uint8 nStatus;
uint8 buf[30];
nStatus = ZLG500_COM_SendReceive(CT_CTRL_DEV, ISOAC_READ_DETECT_DATA, &nDetectMode, 1, buf, sizeof(buf));
if (nStatus == OK)
{
*pTxNumber = buf[0];
memcpy(pCardType, &buf[1], 2);
// *pSAK = buf[3];
memcpy(pCardSN, &buf[5], 4);
if (pBlockData != NULL)
{
memcpy(pBlockData, &buf[5 + buf[4]], 16);
}
}
return nStatus;
}
#endif // PICC_READ_DETECT_DATA_EN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -