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

📄 yuanma.txt

📁 该源码适用于 非接触ic卡的读写 卡用mifare1 读写模块用 AGC 公司的 H6152
💻 TXT
字号:
源程序 
sbit CTRL = P1^0;
sbit BP   = P1^1;

//    密码宏定义  
#define KEY_A 0xaa
#define KEY_B 0xbb
#define KEY_DEFAULT 0xff

//    返回值宏定义 

#define OK      0		     // 操作成功
#define ERR_N  'N'           //	 无卡
#define ERR_F  'F'			 // 操作失败
#define ERR_E  'E'			 // 格式错误
#define ERR_I  'I'			 // 非数值块
#define ERR_X  'X'			 // 操作后无法读出
#define ERR_U  'U'			 // 未知错误

uchar xdata hbuf[0x25];	     // 缓冲区定义
uchar xdata block0buf[16];
uchar xdata block1buf[16];

bit flagok;              //  读写块成功标志位
bit flagfirst;           //  第一次选卡标志位
bit flagselok;           //  选卡成功标志位
bit flaglogok;           //  登录扇区成功标志位
uchar flagwr;            //  写块成功标志位
uchar flagrd;            //  读块成功标志位

uchar count;


//  定时器0中断服务子程序
void timer0() interrupt 1 using 1
{
TR0 = 0;          //  停止计数

TH0 = -5000/256;    //  重新计数初值
TL0 = -5000%256;


count++;
if (count > 300)              //  第一次检测到卡1.5s后 
{
  count = 0;
  if(!flagok)          //    如果检测到1.5s后读写标志还是失败 则蜂鸣器报警
  {
     BP = 0;
	 delay(2000);        //  报警持续两秒
	 BP = 1;
   }
 }
 else 
	TR0 = 1;        //   启动T0 计数
}


//    串口发送命令函数
void sendcmd(uchar *str)
{
   While (*str != 0)
   {
        TI = 0;          //  清发送标志位
		SBUF = *str;     //   发送数据
		str++;
		while(!TI);      //  等待发送完成
	}
}

//  字符数组转换为十六进制字符串函数 十六进制字符串附接在给定字符串后面 
//   参数 BYTE 为数组地址 LEN 为数组长度 str 为转换后字符串 

void Byte2Hex(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;          //   字符串结束
}

//   十六进制字符串转换为字节数组函数 参数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++;
	   }
}

//  串口初始化 
 void serial_init ()
 { 
 	// 9600,N,8,1,外部晶振 11.0592MHz 查询方式
  TMOD = 0X20;       //  T1使用工作方式2
  TH1 = 250;         //  设置T1初值
  TL1 = 250;           
  TR1 = 1;           //  T1开始技计数
  PCON = 0x80;       //  SMOD = 1
  SCON = 0x50;       //  工作方式1 波特率9600bps 允许接收
  ES = 0;            //  关闭串行中断
 }
 
 // H6125复位函数
 void H6152Rst()
 {
 	  strcpy(hbuf,"x");
 	  sendcmd(hbuf);     //  发送命令“x”
 	  delay(300);         //  延时 300ms 确保H6152复位完毕
 	}
 	// 卡片检测函数 检测到有卡片在读写器有效范围内返回
void cardcheck()
{
	strcpy(hbuf,"c");
	sendcmd(hbuf);         // 发送命令“c”命令进入连续续模式
	delay(10);             // 延时 10ms
	
	// 一旦发现串口接受到数据就立即返回 
  // 表示检测到读写器有效区域内有卡片
  RI = 0;
  while (!RI);
  delay(10);       //  延时10ms  消抖
  RI = 0;
  while (!RI);
  // 确认工作区内有卡片  返回
 }
 
 // 停止卡片检测函数 即取消连续续模式
 void endcheck()
 {
 	strcpy(hbuf," ");
 	sendcmd(hbuf);        //   发送取消 连续续 模式
 	delay(10);            //  延时 10ms 
}

// 自动选卡函数  读取所有卡片 随机选中并返回其序列号 主要用于第一次选卡
uchar autoselect( uchar *buf)
{
	uchar i;
	strcpy(hbuf,"m\r");
	sendcmd(hbuf);           //  发送“m<CR>”
	for( i=0; i<8; i++)       //  接收第一张卡的序列号
	{
		   RI = 0;
		   while(!RI);
		   *(hbuf+i) = SBUF;
		   
		   // 如果 接受到错误信息 则返回错误代码
 
		  if((*(hbuf+i)>0x39)&&(*(hbuf+i)<'a'))
		  	return *(hbuf+i);
	}
	*(hbuf+i) = 0;     
Hex2Byte(hbuf,buf);   //  第一张卡片序列号由十六进制字符串转换为字节数组
strcpy(hbug,”m”);
	Byte2Hex(buf,4,hbuf);
	delay(10);
	sendcmd(hbuf);          //  发送“m<sn>” 选中第一张卡片
	for( i=0;i<8;i++)       //  接收选中卡片的序列号
	{ 
		  RI = 0;
		  while(!RI );
		  *(hbuf+i) = SBUF;
		  // 如果接手到错误的信息 则返回错误代码
		 if ((*(hbuf+i)>0x39)&&(*(hbuf+i)<'a'))
		 	return *(hbuf+i);
  }
return 0;              //  成功
}
 //  指定选卡函数 根据制定序列号选卡
 uchar snselect(uchar *sn)
 {
 	uchar i;
 	
 	strcpy(hbuf,"m");
 	Byte2Hex(sn,4,hbuf);    //  将序列号sn 转换为十六进制字符串
 	delay(10);
 	sendcmd(hbuf);        //  发送”m/<sn>” 选中第一张卡片
 	for(i=0; i<8;i++)     //   接收选中卡片的序列号
 	{
 		 RI = 0;
 		 while(!RI);
 		 *(hbuf+i) = SBUF;
 		 
 		 //  如果接受到底错误信息  则返回错误代码 
 	if ((*(hbuf+i)>0x39)&&(*(hbuf+i)<'a'))
		 	return *(hbuf+i);
  }
return 0;  //   成功
}

//  登录扇区函数 参数sect为扇区号 keytrpe为密码类型 keyvalue 为密码内容 
//   vkeyvalue 为null是 表示使用默认密码 keytpe为0X10~0X2f和0X30~ 0X4f
//  之间或者 0Xff时 程序忽略keyvalue的内容
uchar loginsect ( uchar sect,uchar keytype,uchar *keyvalue)
{
	uchar tmp;
	if(sect>16)          //   扇区超过十六 报错
		return EER_E;
		strcpy(hbuf,"1");
		Byte2Hex(&sect,1,hbuf);   // 将sect转换为十六进制字符串
		if(((keytype>0x10)&&(keytype<0x2f))||((keytype>0x30)&&(keytype<0x4f)))
			Byte2Hex(&keytype,1,hbuf);
	else  if((keytype == KEY_A)||(keytype == KEY_B))  //  使用密码A或B登录
		{  
			   Byte2Hex(&keytype,1,hbuf);
			If (keyvalue == NULL)
				strcat(hbuf,"\r");
		   else 
				Byte2Hex(keyvalue,6,hbuf);
		}
		else  if (keytype == KEY_DEFAULT)     //  使用默认密码登录
			strcat(hbuf,"\r");
        else 
           return EER_U;         //   未知错误
			sendcmd(hbuf);       //   发送命令
			RI = 0;
			while(!RI);
			tmp = SBUF ;
			if(tmp == 'l')         //  登录成功
				return 0;
			else                   //  返回错误
				return tmp;
}

//  读块函数 将块中内容读至缓冲区 缓冲区长度应为 16B
uchar readblock(uchar block,uchar *buf)
{
	uchar i;
	if(block>64)           //   块号超过 64 报错
		return EER_E;
		strcpy(hbuf,"r");
		Byte2Hex(&block,1,hbuf);  //  block转换为十六进制字符串
		sendcmd(hbuf);
		 
		 for(i=0;i<32;i++)    //     接收数据块
		 {
		 	RI = 0;
		 	while (!RI);
		 	 *(hbuf+i) = SBUF;
		 	 
		 	 //如果接受到错误信息则返回错误代码 
		 	if((*(hbuf+i)>0x39)&&(*(hbuf+i)<'a'))
		 		return *(hbuf+i);
     }		 		
		 		*(hbuf+32) = 0
		 		Hex2Byte (hbuf,buf);   //  将块内容由十六进制字符串转换为字节数组
		 		return 0;
}		 		

// 写快函数 将缓冲区中内容写入到块 缓冲区长度16B
uchar writeblock(uchar block,uchar *buf)
{
	uchar i;
	if(block>64)          //  块号超过64 报错
		return EER_E;
		strcpy(hbuf,"w");
		Byte2Hex(&block,1,hbuf);  // block 转换为十六进制字符串
		Byte2Hex(buf,16,hbuf);    // 将要写如块的内容转换为十六进制字符串
		sendcmd(hbuf);

		for (i=0;i<32;i++)
		{
			RI = 0;
			while (!RI) ;
			*(hbuf+i) = SBUF ;
			// 如果接收到错误信息  则反会错误代码
			if((*(hbuf+i)>0x39)&&(*(hbuf+i),'a'))
				return *(hbuf_i);
		}
		return 0;   //  成功
}
//  住程序 选取一张卡 将0~5共16个数写入扇区1的块0中 然后再从该扇区的块0中读出这个16个数 存入缓冲区 blockbuf
//  接着在将blockbuf中的内容写入该扇区的块1中 最后在从块1中读出16个数 存入缓冲区 block部分中
//  本设计的主要功能是验证H6125模块对飞接触式ic卡的读写
void main
{
	char sn[4];
	uchar sectno,blockno;           //  扇区号 块号
	uchar blockbuf[16];              // 要写入块的内容缓冲区
	uchar i;
	sectno = 1;                      // 扇区 1
	blockno = 0;                    // 块 0
	flagok = 0;
	flagfirst = 1;
	flagselok = 0;
	flaglogok = 0;
	count = 0;
	for (i=0;i<16;i++)             // 写入0~15共16B
	blockbuf[i]=i;
	CTRL = 0;                        //  H6152正常工作
	BP = 1;                          //  蜂鸣器不发声

	EA = 1;
	TMOD = 0x01;                  //  模式1 T0 为16定时器  计数器
	TH0 = -5000/256;              //  设置计数初值
	TL0 = -5000%256;
	ET0 = 1;                      // 打开T0中断
	serial_init();                //  串口初始化
	H6152Rst();                   //  H6152复位

	while(!flagok)
	{
		cardcheck();
		endcheck();
		if(flagfirst)         //   如果是第一次选卡
			{
				flagfirst = 0;
				if(autoselect(sn)==0)   // 第一张卡片选择成功 并保存序列号sn
					{
						flagselok = 1;
						TR0 = 1;            // T0 开始计时
					}	
	    }
	  else
	    {
	     	if(snselect(sn)==0)      // 指定序列号sn看卡片选择成功
	     			flagselok = 1;
	    }
	   if(flagselok)
	     {
	     	if(loginsect(sectno,KEY_DEFAULT,NULL)== 'L')   // 登录成功
	     		flaglogok = 1;
	     	else
	     		{
	     				flagselok = 0;   // 登录不成功 重新去选卡
	     				flaglogok = 0;
	     		}
	     	if(flaglogok)
	     		{
	     				flagwr = writeblock(blockno,blockbuf);
	     				if(flagwr!=0)
	     						flagselok = 0;     // 写块错误 重新去选卡 
	     				else
	     					{
	     							flagrd = readblock(blockno,blockbuf);
	     							if(flagrd!=0)
	     									flagselok = 0;  // 读块错误重新去选卡
	     							else
	     							{
	     								flagwr = writeblock(blockno+1,block0buf);
	     										if(flagwr!=0)
	     											flagselok = 0; // 写块错误 
                                                                  // 重新选卡
	     									else
	     						{
	     							flagrd = readblock(blockno+1,block1buf);
	     												if(flagrd!=0)
	     														flagselok = 0;
                             //  读块错误  重新去选卡
	     											else
	     												flagok = 1; // 读写成功
	     											}
	     							}

	     					}

	     			}

	     		}

	     }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -