Files

387 lines
11 KiB
C

#include "card_ctrl/card_ctrl.h"
#include "usart.h"
#include "publicdata/publicdata.h"
#include "app_init/app_init.h"
#include "mylog/mylog.h"
#define STX 0x02 //开始符
#define ETX 0x03 //结束符
#define CARD_RET_Y 0x59 //操作成功
#define CARD_RET_N 0x4E //操作失败
#if SYSTEM_TYPE == SYSTEM_TYPE_CCU601E_D
#define CARD_COM_ID E_USART_1
#elif SYSTEM_TYPE == SYSTEM_TYPE_CCU621_M
#define CARD_COM_ID E_USART_0
#else
#define CARD_COM_ID E_USART_0
#endif
#define D_Print_flag (0) //测试打印
#define CARD_BUF_LENGTH 50
#define CARD_RECV_WAIT_TICK 100 //每次等待5个TICK,也就是50ms
#define CARD_RECV_TIMEOUT_CNT 5 //超时计数最大值为10,超时值为500ms
typedef struct
{
U16_T u16_len; //数据域长度
U8_T u8_cmd; //命令字
U8_T u8_para; //命令字参数
U8_T u8_state; //状态字
U8_T u8_data[32]; //数据域
}CARD_CMD_T;
#if 1 //收发接口
/**
* ************************************************************************
* @brief - 数据发送接口函数 发送
*
* @param[in] u8_sendBuf - 发送数据地址
* @param[in] u16_len - 发送数据长度
*
*
* @author jiankalka
* @date 2025-08-07
* ************************************************************************
*/
void v_card_send_data(U8_T *u8_sendBuf , U16_T u16_len)
{
u16_usart_send(CARD_COM_ID,u8_sendBuf, u16_len);
#if D_Print_flag //调试打印
printf("card send,len is [%d]\r\n", u16_len);
printf_hex("--",u8_sendBuf,u16_len);
#endif
}
/**
* ************************************************************************
* @brief - 数据接收接口函数 接收
*
* @param[in] u8_recvBuf - 接收数据地址
* @param[in] u16_len - 预期接收数据长度
*
* @return U16_T - 已接收数据长度
*
* @author jiankalka
* @date 2025-08-07
* ************************************************************************
*/
U16_T u16_card_recv_data(U8_T *u8_recvBuf ,U16_T u16_len)
{
U16_T recv_len;
memset(u8_recvBuf , 0 , u16_len);
recv_len = u16_usart_recv(CARD_COM_ID,u8_recvBuf,u16_len);
#if D_Print_flag //调试打印
if(recv_len == 0) return 0;
printf("card recv,len is [%d]\r\n", recv_len);
printf_hex("--",u8_recvBuf,recv_len);
#endif
return recv_len;
}
#endif
#if 1 //内部控制
/**
* ************************************************************************
* @brief - 组发送帧函数
*
* @param[in] pt_cmd - 发送内容 结构体
*
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
static void v_card_send_cmd(CARD_CMD_T *pt_cmd) //发送
{
U32_T i;
U8_T u8_card_tx_buf[CARD_BUF_LENGTH] = {0};
u8_card_tx_buf[0] = STX;
u8_card_tx_buf[1] = (U8_T)(pt_cmd->u16_len>>8);
u8_card_tx_buf[2] = (U8_T)(pt_cmd->u16_len);
u8_card_tx_buf[3] = pt_cmd->u8_cmd;
u8_card_tx_buf[4] = pt_cmd->u8_para;
for (i=0; i<pt_cmd->u16_len-2; i++)
u8_card_tx_buf[5+i] = pt_cmd->u8_data[i];
u8_card_tx_buf[pt_cmd->u16_len+3] = ETX;
u8_card_tx_buf[pt_cmd->u16_len+4] = u8_calculate_bcc(u8_card_tx_buf, pt_cmd->u16_len+4);
v_card_send_data(u8_card_tx_buf , pt_cmd->u16_len+5);
}
/**
* ************************************************************************
* @brief - 接收数据解帧操作
*
* @param[in] u16_byte_len - 数据长度
* @param[in] u8_card_rx_buf - 数据内容
* @param[in] pt_rx_cmd - 解析存储位置
*
* @return U8_T - 0 解析失败 1解析成功
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
static U8_T u8_card_recv_unpack(U16_T u16_byte_len,U8_T *u8_card_rx_buf ,CARD_CMD_T *pt_rx_cmd)
{
U8_T j;
pt_rx_cmd->u16_len = u16_byte_len;
pt_rx_cmd->u8_cmd = u8_card_rx_buf[3]; //命令字
pt_rx_cmd->u8_para = u8_card_rx_buf[4]; //命令参数
//pt_cmd->u8_state = u8_card_rx_buf[i+5]; //状态字
if(pt_rx_cmd->u8_cmd == 0x34)
{
if(pt_rx_cmd->u8_para == 0x30) //寻卡
{
pt_rx_cmd->u8_state = u8_card_rx_buf[5];
return 1;
}
else if(pt_rx_cmd->u8_para == 0x32) //验证密码
{
pt_rx_cmd->u8_state = u8_card_rx_buf[6];
return 1;
}
else if(pt_rx_cmd->u8_para == 0x33) //读卡号
{
if(u16_byte_len == 0x15) //判长度或判返回状态字是否为0x59
{
pt_rx_cmd->u8_state = u8_card_rx_buf[7];
for(j=0; j<u16_byte_len-5; j++)
{
pt_rx_cmd->u8_data[j] = u8_card_rx_buf[8+j];
}
return 1;
}
}
}
return 0;
}
/**
* ************************************************************************
* @brief - 读卡器收发控制
*
* @param[in] pt_tx_cmd - 发送数据内容
* @param[in] pt_rx_cmd - 对应接收数据内容
*
* @return U32_T -
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
static U32_T u32_card_unpacket(CARD_CMD_T *pt_tx_cmd, CARD_CMD_T *pt_rx_cmd) //解帧
{
U16_T u16_byte_len, u16_rx_len, u16_timeout = 0;
U32_T i, j;
U8_T u8_card_rx_buf[CARD_BUF_LENGTH];
while (u16_timeout++ < CARD_RECV_TIMEOUT_CNT) //是否超时 10
{
v_card_send_cmd(pt_tx_cmd);
mSleep(CARD_RECV_WAIT_TICK); //等待接收
u16_rx_len = u16_card_recv_data(u8_card_rx_buf, CARD_BUF_LENGTH);
if (u16_rx_len <= 5)
continue;
for (i=0; i<u16_rx_len-5; i++)
{
if ((u8_card_rx_buf[i] == STX) //STX
&& (u8_card_rx_buf[i+3] == pt_tx_cmd->u8_cmd) //命令字
&& (u8_card_rx_buf[i+4] == pt_tx_cmd->u8_para)) //命令参数
{
u16_byte_len = ((u8_card_rx_buf[i+1]<<8) | u8_card_rx_buf[i+2]);
if ((u16_rx_len - i) < (u16_byte_len + 5))
{
//logMsg("接收到的为非完整报文\n");
break;
}
else
{
if ((u8_card_rx_buf[i+u16_byte_len+3] == ETX) &&
(u8_card_rx_buf[i+u16_byte_len+4] == u8_calculate_bcc(&u8_card_rx_buf[i], u16_byte_len+4)))
{
//logMsg("card 解帧 校验成功\n");
return u8_card_recv_unpack(u16_byte_len , &u8_card_rx_buf[i] , pt_rx_cmd);
}
}
}
//logMsg("STX校验未通过\n");
}
}
return 0;
}
/**
* ************************************************************************
* @brief - 寻卡操作
*
*
* @return U8_T - 0失败 1成功
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
static U8_T u8_card_seek_card() //寻卡
{
CARD_CMD_T t_card_tx_cmd; //命令
CARD_CMD_T t_card_rx_cmd; //命令
//发送寻卡命令
memset(&t_card_tx_cmd, 0, sizeof(t_card_tx_cmd));
t_card_tx_cmd.u16_len = 2;
t_card_tx_cmd.u8_cmd = 0x34;
t_card_tx_cmd.u8_para = 0x30;
//解包
memset(&t_card_rx_cmd, 0, sizeof(t_card_rx_cmd));
if (u32_card_unpacket(&t_card_tx_cmd, &t_card_rx_cmd) == 1)
{
if (t_card_rx_cmd.u8_state == CARD_RET_Y)
{
return 1;
}
}
return 0;
}
/**
* ************************************************************************
* @brief - 验证密码
*
* @param[in] u8_sectorNo - 扇区号
* @param[in] u8_key - 验证密码
* @param[in] u8_keyLen - 密码长度
*
* @return U8_T - 0失败 1成功
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
static U8_T u8_check_keys(U8_T u8_sectorNo ,const U8_T *u8_key ,U8_T u8_keyLen) //验证密码
{
CARD_CMD_T t_card_tx_cmd; //命令
CARD_CMD_T t_card_rx_cmd; //命令
if(u8_key == NULL || u8_keyLen > 30) return 0;
//发送验证密码命令
memset(&t_card_tx_cmd, 0, sizeof(t_card_tx_cmd));
t_card_tx_cmd.u16_len = 3+u8_keyLen;
t_card_tx_cmd.u8_cmd = 0x34;
t_card_tx_cmd.u8_para = 0x32;
t_card_tx_cmd.u8_data[0] = u8_sectorNo; //扇区号
memcpy(&t_card_tx_cmd.u8_data[1] ,u8_key , u8_keyLen); //扇区密码
//解包
memset(&t_card_rx_cmd, 0, sizeof(t_card_rx_cmd));
if (u32_card_unpacket(&t_card_tx_cmd, &t_card_rx_cmd) == 1)
{
if (t_card_rx_cmd.u8_state == CARD_RET_Y)
{
return 1;
}
}
return 0;
}
/**
* ************************************************************************
* @brief - d读取卡号
*
* @param[in] u8_sectorNo - 扇区号
* @param[in] u8_blockNo -
* @param[in] u8_cardId - 卡号缓存
* @param[in] u8_cardLen - 卡号缓存长度
*
* @return U8_T -
*
* @author jiankalka
* @date 2025-12-04
* ************************************************************************
*/
static U8_T u8_read_card(U8_T u8_sectorNo ,U8_T u8_blockNo ,U8_T *u8_cardId , U8_T u8_cardLen) //读卡号
{
char i,index=0;
unsigned char cardNo_hex[16] = {0};
unsigned char cardNo_ascii[16] = {0};
unsigned char cardNum[18] = {0};
CARD_CMD_T t_card_tx_cmd; //命令
CARD_CMD_T t_card_rx_cmd; //命令
memset(&t_card_tx_cmd, 0, sizeof(t_card_tx_cmd));
t_card_tx_cmd.u16_len = 4;
t_card_tx_cmd.u8_cmd = 0x34;
t_card_tx_cmd.u8_para = 0x33;
t_card_tx_cmd.u8_data[0] = u8_sectorNo;//扇区号
t_card_tx_cmd.u8_data[1] = u8_blockNo;//块号
//解包
memset(&t_card_rx_cmd, 0, sizeof(t_card_rx_cmd));
if(u32_card_unpacket(&t_card_tx_cmd, &t_card_rx_cmd) == 1)
{
if(u8_cardId == NULL) return 1;
memset(u8_cardId, 0, u8_cardLen);
if(t_card_rx_cmd.u16_len-5 > u8_cardLen)
return 0;
memcpy(&u8_cardId[0], &t_card_rx_cmd.u8_data[0], t_card_rx_cmd.u16_len-5);
return t_card_rx_cmd.u16_len-5;
}
return 0;
}
#endif
/**
* ************************************************************************
* @brief - 读卡号
*
* @param[in] u8_data - 卡号接收数据 不接收只读卡时填NULL
* @param[in] u8_len - 读取缓存长度 长度要预留'/0'的位置
*
* @return U8_T - 0 未读取到 非0 已读取到 且为卡号长度
*
* @author jiankalka
* @date 2025-11-28
* ************************************************************************
*/
U8_T u8_read_card_id(U8_T *u8_data , U8_T u8_len)
{
U8_T u8_sectorNo = 0; //扇区
U8_T u8_blockNo = 1; //块
U8_T u8_recvlen;
const U8_T u8_key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //卡密钥
U8_T u8_card[20];
if(u8_card_seek_card() &&
u8_check_keys(u8_sectorNo,u8_key,sizeof(u8_key)))
{
u8_recvlen = u8_read_card(u8_sectorNo,u8_blockNo,u8_card,20);
//printf_hex("card",u8_card,u8_recvlen);
bcd_to_ascii((const U8_T *)u8_card, 8, (char *)u8_data, u8_len); //模块读取卡号最大16位
printf("读取卡号成功 %s\r\n",u8_data);
return u8_recvlen;
}
//printf("读取卡号失败\r\n");
return 0;
}