#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; iu16_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; ju8_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; iu8_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; }