⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mifare1_h6152.c

📁 Mifare1_H6152 的读卡程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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(&sector, 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 + -