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

📄 sle4442.c

📁 IC卡读写程序
💻 C
字号:

#include <reg52.h>
#include "SLE4442.h"
#include <intrins.h>

/* 延时5个us宏定义 */
#define Delay5Us()    _nop_();_nop_();_nop_();_nop_();_nop_()

/* 延时10个us宏定义 */
#define Delay10Us()   _nop_();_nop_();_nop_();_nop_();_nop_();\
					  _nop_();_nop_();_nop_();_nop_();_nop_()

unsigned char bdata ibase;		//定义位寻址单元,用于发送与接收
								//一个字节
sbit mybit0 = ibase^0;
sbit mybit1 = ibase^1;
sbit mybit2 = ibase^2;
sbit mybit3 = ibase^3;
sbit mybit4 = ibase^4;
sbit mybit5 = ibase^5;
sbit mybit6 = ibase^6;
sbit mybit7 = ibase^7;

/***************************************************************
函数名称:Readchar
功	  能:读一个字节
输	  入: 无
输	  出:所得的字节的值 
****************************************************************/
unsigned char Readchar(void)
{
	CLK = 0; Delay5Us(); mybit0 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit1 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit2 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit3 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit4 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit5 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit6 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	CLK = 0; Delay5Us(); mybit7 = IO; CLK = 1; Delay5Us();	//一个脉冲接收1 bit
	
	return(ibase);		//返回读得的一个字节
}

/************************************************************
函数名称:SendByte
功    能:把一个字节的数据由低到高位依次发送出去
输	  入:unsigned char sendchar --- 要发送的字节
输	  出;无
*************************************************************/
void SendByte(unsigned char sendchar)
{	
	unsigned char i = 8;
	ibase = sendchar;

	for(; i > 0; i--)			//8个比特发送8次
	{							
		CLK = 0;		
		Delay5Us();
		IO  = mybit0;			//一个脉冲发送一个比特mybit0
		CLK = 1;
		Delay5Us();
		ibase = ibase>>1;		//将下次要发送的比特位移到mybit0
	}
}


/***********************************************************
函数名称:RstCard
功    能:使IC卡SLE4442复位
输	  入:无
输	  出:0 --- 复位成功
	      1 --- 复位失败,卡为无效卡或卡已损坏 
************************************************************/
unsigned char RstCard(void)
{
	unsigned char i;
	unsigned char ReadBuf[4];

	IO  = 1;				//IO  引脚置高电平			
	RST = 0;				//RST 引脚置低电平
	CLK = 0;				//CLK 引脚置低电平

	Delay10Us();			//下面在一个RST脉冲期间产生一个CLK脉冲
	RST = 1;
	Delay5Us();
	CLK = 1;
	Delay5Us();
	CLK = 0;
	Delay5Us();
	RST = 0;
							//接收复位响应值
	for(i = 0; i < 4; i++)
	{
		ReadBuf[i] = Readchar();
	}

	CLK = 1;
	Delay5Us();		
	CLK = 0;		
	IO  = 1; 				//置CLK和IO为复位时序图复位完成时的状态		
	
	if ((ReadBuf[0] == IDENTIFY1) && (ReadBuf[1] == IDENTIFY2) &&
	    (ReadBuf[2] == IDENTIFY3) && (ReadBuf[3] == IDENTIFY4))
	{	
		return 0;			//复位值正确,返回复位成功
	}
	else
	{
		return 1;			//复位值错误,返回复位失败
	}  
}


	
/************************************************************
函数名:SendCommand
功  能:根据不同的参数把命令字发给IC卡
参  数:unsigned char command  --- 命令字;
		unsigned char Address  --- 地址;
		unsigned char senddata --- 数据
返回值:无
*************************************************************/
void SendCommand(unsigned char command,unsigned char Address,unsigned char senddata)
{
	IO  = 1;			/*产生开始状态*/
	CLK = 0;
	Delay5Us();
	CLK = 1;
	Delay10Us();
	IO = 0;
	Delay10Us();
	CLK = 0;
						/*发送命令*/
	SendByte(command);
	SendByte(Address);
	SendByte(senddata);
						/*产生停止状态*/
	CLK = 0;
 	IO  = 0;
	Delay5Us();
	CLK = 1;
	Delay5Us();
	IO  = 1;
	Delay5Us();
}

/****************************************************************
函数名称:SendClock
功    能:发送处理脉冲
输    入:无
输	  出:无
*****************************************************************/
void SendClock(void)
{	
	CLK=0;				//产生一个脉冲,做为处理的工始
	Delay10Us();
	CLK=1;
	Delay10Us();

	do
	{
		CLK=0;			
		Delay10Us();
		CLK=1;
		Delay10Us();
	}while(IO == 0);	//不断产生处理脉冲,驱动IC卡内部处理,直到IC卡将
}						//IO口拉为高电平

/***************************************************************
函数名称:ReadCm
功    能:从主存储器中读出数据块并存入ReadBuf中
输	  入:unsigned char StarAddr --- 开始地址(0 - 255)
		  unsigned char ByteNum  --- 要读出的字节数(1 - 256)
		  unsigned char *RecBuf  --- 接收数据缓冲区
输	  出: 0 --- 读成功
		  1 --- 表示无效卡或者卡损坏	
****************************************************************/
unsigned char ReadCm(unsigned char StarAddr,unsigned char ByteNum,unsigned char *RecBuf)
{
	unsigned char i = 0;

	if (RstCard() == 1)						/* 使卡复位*/
		return 1;							/* 如果复位失败返回1 */
		
	SendCommand(0x30,StarAddr,0x00);		/* 发送读主存命令 */

	for(i = 0; i < ByteNum; i++)
	{
		*RecBuf = Readchar();			    /* 从主存中读出ByteNum个字节并存入RecBuf中 */
		RecBuf++;
	}
		return 0;
}

/****************************************************************
函数名称: WriteCm
功    能: 把存在WriteBuf中的ByteNum个字节的数据存入主存储器中
输    入: unsigned char StarAdr   --- 开始地址(0 - 255)
          unsigned char ByteNum   --- 要写入的字节数(1 - 256)
	      unsigned char *WriteBuf --- 写入数据缓冲区	
输	  出: 0 --- 写成功
		  1 --- 表示无效卡或者卡损坏
注	  意:要校验密钥正确,才能对卡的主存储器写入数据	
*****************************************************************/
unsigned char WriteCm(unsigned char StarAdr,unsigned char ByteNum,unsigned char *WriteBuf)
{
	unsigned char i = 0;

	if (RstCard() == 1)						    /* 使卡复位*/
		return 1;							    /* 如果复位失败返回1 */

	for(i = 0; i < ByteNum; i++)
	{
		SendCommand(0x38,StarAdr,*WriteBuf);	//发送写主存储区命令
		SendClock();							//发送处理脉冲		
		StarAdr++;								//写入字节地址加1
		WriteBuf++;								//写入缓冲区指针加1
	}
		return 0;
}

/******************************************************************
函数名称:ReadPm
功    能:读保护存储器,并把保护存储器的4字节的内容存在RecBuf中
输	  入:unsigned char *RecBuf  --- 接收数据缓冲区,长度为4个字节
输    出:0 --- 读成功
		  1 --- 表示无效卡或者卡损坏	
*******************************************************************/
unsigned char ReadPm(unsigned char *RecBuf)
{
	unsigned char i = 0;

	if (RstCard() == 1)					/* 使卡复位*/
		return 1;						/* 如果复位失败返回1 */

	SendCommand(0x34,0x00,0x00);		//读保护存储器命令		

	IO = 1;								// 置IO口为输入状态
	Delay10Us();						// 延时一下

	for(i = 0; i < 4; i++)				//读保护存储器4个字节
	{
		*RecBuf=Readchar();
		RecBuf++;						//接收缓冲区指针加1
	}

	SendClock();						//发送处理脉冲	

	return 0;
}

/********************************************************************
函数名称:WritePm
功    能:写保护数据存储器
输	  入:unsigned char StartAdr  --- 起始地址(0 - 31)
	      unsigned char ByteNum   --- 写入的字节数(1 - 32)
	 	  unsigned char *WriteBuf --- 写入数据缓冲区
输	  出:0 --- 写成功
		  1 --- 表示无效卡或者卡损坏	
注	  意: 首先校验密钥正确,才能对卡的护存储器写入数据,
          其次写入的数据必须与卡中对应的数据相等才能写入
*********************************************************************/
unsigned char WritePm(unsigned char StartAdr,unsigned char ByteNum,unsigned char *WriteBuf)
{
	unsigned char i;

	if (RstCard() == 1)							/* 使卡复位*/
		return 1;								/* 如果复位失败返回1 */

	for (i = 0; i < ByteNum; i++)
	{
		SendCommand(0x3c,StartAdr,*WriteBuf);	//写入一个字节
		SendClock();							//发送写命令处理脉冲
		StartAdr++;								//写入字节地址加1
		WriteBuf++;								//写入缓冲区指针加1
	}	
		return 0;
}

/**********************************************************************
函数名称:ReadPsw
功    能:读加密存储器
输	  入:unsigned char *Psw  --- 用于装读到的加密存储器内容,长度为4个字节
		  Psw第一字节: 			 错误计数器值
		  Psw第二字节到第四字节: 卡的密码值
输	  出:0 --- 读成功
		  1 --- 表示无效卡或者卡损坏
注	  意: 必须校验密码正确才能读到正确的密钥值,否则读到的密码值为00 00 00
***********************************************************************/
unsigned char ReadPsw(unsigned char *Psw)
{
	unsigned char i = 0;

	if (RstCard() == 1)					/* 使卡复位*/
		return 1;						/* 如果复位失败返回1 */

	SendCommand(0x31,0,0);				//读加密存储器命令

	for(i = 0; i < 4; i++)				//读加密存储器的四个字节
	{
		*Psw = Readchar();			
		Psw++;
	}	
		return 0;
}

/*********************************************************************
函数名称:CheckPsw
功    能:校验密码,把Psw中1,2,3字节的内容分别与加密存储器的1,2,3字节比较
输	  入:unsigned char *Psw  --- 待校验的密码值,长度为3个字节
输    出: 3: 核对密码成功
	      0: 卡已报废
	   	  1: 只剩一次校验机会,校验密码失败
	      2: 只剩二次校验机会,校验密码失败
		  4: 卡为无效卡或已损坏
**********************************************************************/
unsigned char CheckPsw(unsigned char *Psw)
{
	unsigned char ReadBuf[4];			
	unsigned char i = 0;

	if (ReadPsw(ReadBuf) == 1)			//读加密存储器
		return 4;

	if(ReadBuf[0]==0x07)			
	{
		SendCommand(0x39,0,0x03);		//将EC写为0x03
		SendClock();						//发送处理脉冲
	}
	else if(ReadBuf[0]==0x06 || ReadBuf[0]==0x05 || ReadBuf[0]==0x03)
	{
		SendCommand(0x39,0,0x01);		//将EC写为0x01
		SendClock();						//发送处理脉冲
	}
	else if(ReadBuf[0]==0x01 || ReadBuf[0]==0x02 || ReadBuf[0]==0x04)
	{
		SendCommand(0x39,0,0x00);		//将EC写为0x00
		SendClock();						//发送处理脉冲
	}
			
	SendCommand(0x33,1,Psw[0]);			//校验密码的第一个字节
	SendClock();							
	SendCommand(0x33,2,Psw[1]);			//校验密码的第二个字节
	SendClock();
	SendCommand(0x33,3,Psw[2]);			//校验密码的第三个字节
	SendClock();
	
	SendCommand(0x39,0,0x07);			//擦除错误计数器
	SendClock();

	SendCommand(0x31,0,0);				//读加密存储器命令	

	for(i = 0;i < 4;i++)
	{
		ReadBuf[i]=Readchar();			//读加密存储器的四个字节
	}
	
	if(ReadBuf[0] == 0x07) return 3;	//剩下3次校验机会,校验密码成功
	else if(ReadBuf[0] == 0x06 || ReadBuf[0] == 0x05 || ReadBuf[0] == 0x03) return 2;
										//剩下2次校验机会,校验密码失败
	else if(ReadBuf[0] == 0x04 || ReadBuf[0] == 0x02 || ReadBuf[0] == 0x01) return 1;
										//剩下1次校验机会,校验密码失败		
	else return 0;						//剩下0次校验机会,卡报废
}

/**********************************************************************
函数名称:SetPsw
功    能:修改加密存储器中的密码
输	  入:NewPsw -- 新密码缓冲区,长度为3个字节
输	  出:0 --- 读成功
		  1 --- 表示无效卡或者卡损坏
注	  意: 必须校验密码成功后才能修改密码, 否则密码写不进卡中
***********************************************************************/
unsigned char SetPsw(unsigned char *NewPsw)
{
	unsigned char i;

	if (RstCard() == 1)							/* 使卡复位*/
		return 1;								/* 如果复位失败返回1 */

	for (i = 0; i < 3; i++)
	{
		SendCommand(0x39,i + 1,*NewPsw);		//发送新的密码值
		SendClock();							//发送处理脉冲
		NewPsw++;								//密码值缓冲区指针加1
	}	
		return 0;
}


⌨️ 快捷键说明

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