📄 mifare1_h6152.c
字号:
/* Mifare1_H6152.c */
/*********************************************************************
* 程序说明:Mifare1读写模块H6152(德国ACG公司)操作函数库
* ASCII协议,默认设置,使用查询方式发送接收,调用前建议添加超时控制
* 使用语言:C51
* 编译工具:Keil uVision2.38a
* 作者:djws
* 版本:v1.2
* 时间:2004.7
*********************************************************************/
#ifndef __MIFARE1_H6152_C__
#define __MIFARE1_H6152_C__
#define _MHZ_ 11
#define uchar unsigned char
#define uint unsigned int
#include <reg51.h>
#include <string.h>
#include <intrins.h>
/* 密码类型 */
enum
{
M_KEY_A = 0xaa, /* 使用密码A */
M_KEY_B = 0xbb, /* 使用密码B */
M_KEY_DEFAULT = 0xff /* 使用默认密码 */
};
/* 返回值类型 */
enum
{
M_OK = 0, /* 操作成功 */
M_ERR_N = 'N', /* 无卡 */
M_ERR_F = 'F', /* 操作失败 */
M_ERR_E = 'E', /* 格式错误 */
M_ERR_I = 'I', /* 非数值块 */
M_ERR_X = 'X', /* 操作后无法读出 */
M_ERR_U = 'U' /* 未知错误 */
};
uchar m_buf[0x25]; // 缓冲区
/* 文件内部函数声明 */
void delay10ms(uint count); /* 延时10ms */
void m_send_cmd(uchar *str); /* 串口发送命令 */
void Byte2HexCat(uchar *byte, uchar len, uchar *str); /* 字符数组转换为16进制字符串并附接至给定字符串后 */
void Hex2Byte(uchar *str, uchar *byte); /* 16进制字符串转换为字符数组 */
/* 延时10ms,精度较低,参数count为延时时间 */
void delay10ms(unsigned int count)
{
unsigned int i, k;
unsigned char j;
unsigned int tmp;
tmp = (int)((100*_MHZ_)/12);
for(i=0; i<count; i++)
for(j=0; j<100; j++)
for(k=0; k<tmp; k++);
}
/* 串口发送命令 */
void m_send_cmd(uchar *str)
{
while(*str != 0)
{
TI = 0; // 清发送标志位
SBUF = *str; // 发送数据
str++;
while(!TI); // 等待发送完成
}
}
/* 字符数组转换为16进制字符串,并附接至给定字符串后
* 参数byte为数组地址,len为数组长度,str为转换后字符串
*/
void Byte2HexCat(uchar *byte, uchar len, uchar *str)
{
uchar i, j;
uchar tmp;
j = strlen(str);
for(i=0; i<len; i++)
{
tmp = ((*byte)>>4)&0x0f; // 字节高位
if(tmp < 0x0a)
*(str+j) = tmp+0x30;
else
*(str+j) = tmp-0x0a+'a';
str++;
tmp = (*byte)&0x0f; // 字节低位
if(tmp < 0x0a)
*(str+j) = tmp+0x30;
else
*(str+j) = tmp-0x0a+'a';
str++;
}
*(str+j) = 0; // 字符串结束
}
/* 16进制字符串转换为字符数组
* 参数str为要转换的字符串,byte为转换后数组地址,若str长度不为偶数,则转换后最后一个字节高位补0
*/
void Hex2Byte(uchar *str, uchar *byte)
{
uchar tmp;
while(*str != 0)
{
tmp = ((*str)<<4)&0xf0; // 字节高位
str++;
if(*str == 0) // 如果str长度为奇数,则转换后最后一个字节高位补0
{
*byte = (tmp>>4)&0x0f;
return;
}
tmp += (*str)&0x0f; // 字节低位
*byte = tmp;
byte++;
}
}
/* H6152复位 */
void m_reset()
{
strcpy(m_buf, "x");
m_send_cmd(m_buf); // 发送命令"x"
delay10ms(25); // 延时250ms
// 软复位方式下,H6152在178ms后进入Continuous Read模式,因此延时250ms可以确保H6152复位完毕
}
/* 启动卡片检测,检测到有卡在读卡器区域时返回 */
void m_start_check()
{
strcpy(m_buf, " ");
m_send_cmd(m_buf); // 发送" "取消Continuous Read模式
delay10ms(1); // 延时10ms
m_buf[0] = 'c';
m_send_cmd(m_buf); // 发送命令"c"
delay10ms(1); // 延时10ms
/* 检测读写器工作区域是否有卡片存在 */
RI = 0; // 清接收标志位
while(!RI); // 接收到数据前等待
delay10ms(1); // 消抖
RI = 0;
while(!RI);
/* 确认工作区内有卡片,返回 */
}
/* 取消Continuous Read模式 */
void m_end_con()
{
strcpy(m_buf, " ");
m_send_cmd(m_buf); // 发送" "取消Continuous Read模式
delay10ms(1); // 延时10ms
}
/* 由读卡器自动选择有效区域内卡片,并返回其序列号,参数buf用于保存返回的序列号 */
uchar m_auto_select(uchar *buf)
{
uchar i;
strcpy(m_buf, "m\r");
m_send_cmd(m_buf); // 发送"m<CR>"
for(i=0; i<8; i++) // 接收第一张卡的序列号
{
RI = 0;
while(!RI);
*(m_buf+i) = SBUF;
if((*(m_buf+i)>0x39) && (*(m_buf+i)<'a')) // 如果接收到错误信息则直接返回错误代码
return *(m_buf+i);
}
*(m_buf+8) = 0;
Hex2Byte(m_buf, buf); // 将第一张卡的序列号由16进制字符串形式转换为字节数组
strcpy(m_buf, "m");
Byte2HexCat(buf, 4, m_buf);
delay10ms(1);
m_send_cmd(m_buf); // 发送"m<SN>",选中第一张卡片
for(i=0; i<8; i++) // 接收选中卡片的序列号
{
RI = 0;
while(!RI);
*(m_buf+i) = SBUF;
if((*(m_buf+i)>0x39) && (*(m_buf+i)<'a')) // 如果接收到错误信息则直接返回错误代码
return *(m_buf+i);
}
return 0; // 操作成功
}
/* 根据指定序列号选卡 */
uchar m_select(uchar *sn)
{
uchar i;
strcpy(m_buf, "m");
Byte2HexCat(sn, 4, m_buf); // 将SN转换为16进制字符串
m_send_cmd(m_buf); // 发送"m<SN>",选中第一张卡片
for(i=0; i<8; i++) // 接收选中卡片的序列号
{
RI = 0;
while(!RI);
*(m_buf+i) = SBUF;
if((*(m_buf+i)>0x39) && (*(m_buf+i)<'a')) // 如果接收到错误信息则直接返回错误代码
return *(m_buf+i);
}
return 0; // 操作成功
}
/* 登陆指定扇区
* 参数sector为要登陆的扇区,keytype为登陆时使用的密码类型,keyvalue为密码内容
* keyvalue值为NULL时表示使用默认密码,对应命令如下
* m_login(sector, M_KEY_DEFAULT, NULL) 对应命令"l<sector><CR>"
* m_login(sector, M_KEY_A, NULL) 对应命令"l<sector>aa<CR>"
* m_login(sector, M_KEY_B, NULL) 对应命令"l<sector>bb<CR>"
* keytype值为0x10-0x2f和0x30-0x4f之间或M_KEY_DEFAULT时,程序忽略keyvalue的内容
*/
uchar m_login(uchar sector, uchar keytype, uchar *keyvalue)
{
uchar tmp1;
if(sector > 16) // 扇区值超过16报错
return M_ERR_E;
strcpy(m_buf, "l");
Byte2HexCat(§or, 1, m_buf); // 将sector转换为16进制字符串
if(((keytype>0x10)&&(keytype<0x2f)) || ((keytype>0x30)&&(keytype<0x4f))) // 使用密码寄存器00..2F中的内容
Byte2HexCat(&keytype, 1, m_buf); // "l<sector><reg>"
else if((keytype==M_KEY_A) || (keytype==M_KEY_B)) // 使用密码A或密码B登陆
{
Byte2HexCat(&keytype, 1, m_buf); // 将keytype转换为16进制字符串
if(keyvalue == NULL)
strcat(m_buf, "\r"); // "l<sector>aa<CR>"或"l<sector>bb<CR>"
else
Byte2HexCat(keyvalue, 6, m_buf); // "l<sector>aa<value>"或"l<sector>bb<value>"
}
else if(keytype == M_KEY_DEFAULT) // 使用默认密码A登陆
{
strcat(m_buf, "\r"); // "l<sector><CR>"
}
else
return M_ERR_U; // 未知错误
m_send_cmd(m_buf); // 发送命令
RI = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -