FM4442IC卡通信协议(SLE4442)

FM4442IC卡通信协议(SLE4442)

基于STM32F103CBT6的IC卡协议


1.原理图设计


其中GPIOA15为JTAG引脚,固需要把JTAG功能禁用!!!

代码如下:

__HAL_RCC_AFIO_CLK_ENABLE();//在stm32f1xx_hal_gpio.c文件中
__HAL_AFIO_REMAP_SWJ_NOJTAG();
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
	
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_SWJ_NOJTAG();
  /* Configure the port pins */

2.IC卡存储区介绍

在这里插入图片描述
1、棕色数据为出场数据 表明卡类型等无法修改。
2、粉色数据为写保护区 即写入后无法修改。
3、绿色数据为厂商标识 可以联系厂商在出场时写入。
4、白色数据为正常存储区 可多次写入与擦除。

3.IC芯片手册

1.IC卡引脚图
在这里插入图片描述
2.IC卡复位与应答时序
在这里插入图片描述

3.命令模式时序
在这里插入图片描述
4.数据输出时序
在这里插入图片描述
5.处理模式时序
在这里插入图片描述
6.中止时序
在这里插入图片描述

4.程序.c

代码如下:

/*
*********************************************************************************************************
头文件
*********************************************************************************************************
*/
#include "stm32f1xx_hal.h"
#include "ic.h"
/*
*********************************************************************************************************
全局变量定义
*********************************************************************************************************
*/
unsigned char WRC_Structure;


/*
*********************************************************************************************************
函数名称:ic_Init
功    能:初始化ic卡的引脚
输	  入:无
输	  出:无
注	  意:PA15为	JTAG脚调试脚,需禁用JTAG功能
*********************************************************************************************************
*/
void ic_Init(void)
{
		GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  __HAL_RCC_GPIOB_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}
/*
*********************************************************************************************************
函数名称:Delay_Us
功    能:实现us级延时
输	  入:无
输	  出:无
*********************************************************************************************************
*/
void Delay_Us(unsigned char i)
{
	for(;i!=0;i--) 
  __NOP();
}

/*
*********************************************************************************************************
函数名称:Start_IC_IC
功    能:IC卡开始时序
输	  入:无
输	  出:无
*********************************************************************************************************
*/
void Start_IC(void)
{
	SDA_OUT();
	SCL      = 0;	  //钳住总线,准备发送数据 
	SLE_DATA = 1;	    		 
	SCL      = 1;
	Delay_Us(10);   //起始条件建立时间大于4.7us,延时		 
	SLE_DATA = 0;	  //发送起始信号
	Delay_Us(10);   //起始条件锁定时间大于4us		 
	SCL      = 0;	  //钳住总线,准备发送数据 
	Delay_Us(10);
}		
/*
*********************************************************************************************************
函数名称:Stop_IC_IC
功    能:IC卡停止时序
输	  入:无
输	  出:无
*********************************************************************************************************
*/
void Stop_IC(void)//结束命令模式
{	
		SDA_OUT();
		SLE_DATA = 0;
		Delay_Us(10);
		SCL      = 1;
		Delay_Us(10); //结束条件建立时间大于4us,延时		 
		SLE_DATA = 1;	//发送起始信号
		Delay_Us(10);
}
/*
*********************************************************************************************************
函数名称:WR_Byte
功    能:写字节函数
输	  入:unsigned char txd --- 要写入的数据
输	  出:无
*********************************************************************************************************
*/				  
void WR_Byte (unsigned char txd)
{ 
	unsigned char i = 0;
	
	SDA_OUT();
	
	for(i=0;i<8;i++)
	{			
		if(txd&0x01) SLE_DATA = 1;
		else SLE_DATA = 0;
		Delay_Us(10);
		SCL = 1;
		Delay_Us(10);
		SCL = 0;
		txd >>= 1;
	}		
}
/*
*********************************************************************************************************
函数名称:RD_Byte
功    能:读字节函数
输	  入:无
输	  出:receive --- 读取到的数据
*********************************************************************************************************
*/	
unsigned char RD_Byte (void)
{
	unsigned char i = 0,receive = 0;
	
	SDA_IN();//置数据线为输入方式
	
	for(i=0;i<8;i++)
	{
		SCL = 0;				      //置时钟线为低准备接收数据位
		Delay_Us(10);
		SCL = 1;				      //置时钟线为高使数据线上数据有效
		Delay_Us(10);
		receive >>= 1;
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15)) receive|=0X80;   //读数据位,接收的数据位放入x
	}				   
	SCL = 0;
	Delay_Us(10); 
	SDA_OUT();
	
	return receive;	

}
/*
*********************************************************************************************************
函数名称:byte_read_4442_a
功    能:读保护位字节函数
输	  入:无
输	  出:cTemp --- 读取到的数据
*********************************************************************************************************
*/	
unsigned char byte_read_4442_a(void)
{
	unsigned char cTemp = 0x00,i = 0x00;
	
	SLE_DATA = HIGH;
	
	SDA_IN();
	for(i=0;i<8;i++)
	{
		cTemp*=2;
		SCL = 1;
		Delay_Us(10);
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15) == HIGH)
			cTemp++;
		SCL = 0;
		Delay_Us(10);
	}
	return cTemp;
}
/*
*********************************************************************************************************
函数名称:RstCard
功    能:使IC卡FM4442复位
输	  入:无
输	  出:0 --- 复位成功
	        1 --- 复位失败,卡为无效卡或卡已损坏 
*********************************************************************************************************
*/
unsigned char RstCard(void)//复位
{
  unsigned char i = 0;
	unsigned char ReadBuf[4] = {0};
 
	SDA_OUT(); 
	
	RST = LOW;
	SCL = LOW;
	Delay_Us(10);
	RST = HIGH;//产生复位时序
	Delay_Us(10);
	SCL = HIGH;
	Delay_Us(20);
	SCL = LOW;
	Delay_Us(10);
	RST = LOW;	  
	
	for(i = 0; i < 4; i++)
	{
		ReadBuf[i] = RD_Byte();
	}

	SCL      = HIGH;
	Delay_Us(5);
	SCL      = LOW;
	SLE_DATA = HIGH;	
	
	if ((ReadBuf[0] == SLE4442ID1) && (ReadBuf[1] == SLE4442ID2) && (ReadBuf[2] == SLE4442ID3) && (ReadBuf[3] == SLE4442ID4))
	{	
		return 0;			//复位值正确,返回复位成功
	}
	else
	{

		return 1;			//复位值错误,返回复位失败
	}
}

/*
*********************************************************************************************************
函数名称:Wait_IC_IC
功    能:等待时序
输	  入:无
输	  出:0 --- 等待成功
	        1 --- 等待失败
*********************************************************************************************************
*/
unsigned char Wait_IC(void)
{
	unsigned char i = 0;
	
	SDA_OUT();
	SLE_DATA = 0;	 		
	while(i<255)
	{
		i++;
		SCL = 0;
		Delay_Us(10);
		SCL = 1;
		Delay_Us(10); 
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15))
		{
			SDA_OUT();
			return 0;//内部处理模式已经完成了.  
		}
	}
	SDA_OUT();
	return 1;//等待失败.
}
/*
*********************************************************************************************************
函数名称:Break_IC_IC
功    能:终止时序
输	  入:无
输	  出:无
*********************************************************************************************************
*/
void Break_IC(void)
{
	SCL = 0;
	Delay_Us(10);
	SCL = 1; 	//发出中止操作的时序 
	Delay_Us(10);
	SCL = 0;
}
/*
*********************************************************************************************************
函数名称:WR_Cmd
功    能:写命令到ic卡
输	  入:unsigned char cmd --- 命令
					unsigned char addr --- 写入地址
					unsigned char dat --- 写入数据
输	  出:无
*********************************************************************************************************
*/
void WR_Cmd(unsigned char cmd,unsigned char addr,unsigned char dat)
{
	Start_IC(); 		    //开始
	WR_Byte(cmd);	  //发送命令  
	WR_Byte(addr); 	//写地址
	WR_Byte(dat); 	//写数据
	Stop_IC(); 		    //停止
}
/*
*********************************************************************************************************
函数名称:Read
功    能:写命令到ic卡
输	  入:unsigned char area --- 读地址范围
					unsigned char addr --- 读取起始地址
					unsigned char dat --- 读到的数据
输	  出:无
*********************************************************************************************************
*/
void Read_IC(unsigned char area, unsigned char addr, unsigned char len, unsigned char *buf)
{
	unsigned char i = 0; 
  
	RstCard();
	WR_Cmd(area,addr,0);
	for (i=0;i<len;i++)	//读取数据
	{ 					
		buf[i] = RD_Byte();
	}			    
}
/*
*********************************************************************************************************
函数名称:Write
功    能:写命令到ic卡
输	  入:unsigned char area --- 写入地址范围
					unsigned char addr --- 写入起始地址
					unsigned char *buf --- 写入数据
输	  出:无
*********************************************************************************************************
*/
unsigned char Write_IC(unsigned char area,unsigned char addr,unsigned char len,unsigned char *buf)
{
	unsigned char i = 0,sta = 0;
	
	RstCard();
	
	for(i=0;i<len;i++)
	{
		WR_Cmd(area|0X08,addr+i,buf[i]);//发送命令 0X38/0X39/0X3C  地址+数据
		sta = Wait_IC();	  		//发送操作脉冲
		if(sta) Break_IC();			    //超时了
	}
	return sta;
} 
/*
*********************************************************************************************************
函数名称: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(StarAddr>255)
		return 1;
	
	if((256-StarAddr) < ByteNum)
		return 1;

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

	for(i = 0; i < ByteNum; i++)
	{
		*RecBuf = RD_Byte();			    /* 从主存中读出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)
{
	volatile unsigned char writebuf[ByteNum];
	unsigned char i = 0;
	volatile unsigned char sta = 0;
	
	if(StarAdr>255)
		return 1;
	
	if((256-StarAdr) < ByteNum)
		return 1;	

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

	for(i = 0; i < ByteNum; i++)
	{
		writebuf[i] = *WriteBuf;
		WR_Cmd(WRITE_MRAM,StarAdr,writebuf[i]);	//发送写主存储区命令
		sta = Wait_IC();	  		                  //发送操作脉冲

		StarAdr++;								                //写入字节地址加1
		WriteBuf++;								                //写入缓冲区指针加1
	}
		return 0;
}
/****************************************************************
函数名称:SendClock
功    能:发送处理脉冲
输    入:
输	  出:
*****************************************************************/
void SendClock(void)
{	
	SDA_IN();
	SCL=0;				//产生一个脉冲,做为处理的工始
	Delay_Us(10);
	SCL=1;
	Delay_Us(10);

	do
	{
		SCL=0;			
	  Delay_Us(10);
		SCL=1;
	  Delay_Us(10);
	}while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15) == 0);	//不断产生处理脉冲,驱动IC卡内部处理,直到IC卡将IO口拉为高电平
}
/*
*********************************************************************************************************
函数名称: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 */

	WR_Cmd(READ_PRAM,0x00,0x00);		//读保护存储器命令		
	for(i = 0; i < 32; i++)				      //读保护存储器4个字节
	{
		*RecBuf = RD_Byte();
		RecBuf++;						              //接收缓冲区指针加1
	}
	
	return 0;
}
/*
*********************************************************************************************************
函数名称:WritePm
功    能:写保护数据存储器
输	  入:unsigned char Start_ICAdr  --- 起始地址(0 - 31)
	        unsigned char ByteNum   --- 写入的字节数(1 - 32)
	 	      unsigned char *WriteBuf --- 写入数据缓冲区
输	  出:0 --- 写成功
					1 --- 表示无效卡或者卡损坏	
注	  意: 首先校验密钥正确,才能对卡的保护存储器写入数据,
          其次写入的数据必须与卡中对应的数据相等才能写入
					即 WriteCm();WritePm();
*********************************************************************************************************
*/
unsigned char WritePm(unsigned char Start_ICAdr,unsigned char ByteNum,unsigned char *WriteBuf)
{
	unsigned char i,sta = 0;
	
	if(Start_ICAdr>31)
		return 1;
	
	if(ByteNum>(32-Start_ICAdr))
		return 1;

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

	for (i = 0; i < ByteNum; i++)
	{
		WR_Cmd(WRITE_PMEM,Start_ICAdr,*WriteBuf);	//写入一个字节
		sta = Wait_IC();	  		                    //发送操作脉冲
		if(sta) Break_IC();			                        //超时了
		Start_ICAdr++;								                  //写入字节地址加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 */

	WR_Cmd(READ_PSCR,0,0);				//读加密存储器命令

	for(i = 0; i < 4; i++)				//读加密存储器的四个字节
	{
		*Psw = RD_Byte();		
    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,count;
	volatile unsigned char Psw[3];
	for(count=0;count<3;count++)
	{
		Psw[count] = *psw;
		psw++;
	}
	if(ReadPsw(ReadBuf) == 1)			          //读加密存储器
		return 4;
	
	if(ReadBuf[0]==0x07)			 	//0x07
	{
		WR_Cmd(WRITE_SAFE_MEM,0,0x03);		//将EC写为0x03
		Wait_IC();	  		                    //发送操作脉冲
	}
	else if(ReadBuf[0]==0x06 || ReadBuf[0]==0x05 || ReadBuf[0]==0x03)
	{
		WR_Cmd(WRITE_SAFE_MEM,0,0x01);	  //将EC写为0x01
		Wait_IC();	  		                    //发送操作脉冲
	}
	else if(ReadBuf[0]==0x01 || ReadBuf[0]==0x02 || ReadBuf[0]==0x04)
	{
		WR_Cmd(WRITE_SAFE_MEM,0,0x00);		//将EC写为0x00
		Wait_IC();	  		                    //发送操作脉冲
	}
	
	WR_Cmd(SLE_PSC_CHK,1,Psw[0]);//校验密码的第一个字节
	Wait_IC();	  		                      //发送操作脉冲							
	WR_Cmd(SLE_PSC_CHK,2,Psw[1]);//校验密码的第二个字节
	Wait_IC();	  		                      //发送操作脉冲
	WR_Cmd(SLE_PSC_CHK,3,Psw[2]);//校验密码的第三个字节
	Wait_IC();	  		                      //发送操作脉冲
//	
	WR_Cmd(WRITE_SAFE_MEM,0,0XFF);			//擦除错误计数器
	Wait_IC();	  		                      //发送操作脉冲

	WR_Cmd(READ_PSCR,0,0);				      //读加密存储器命令	

	for(i = 0;i < 4;i++)
	{
		ReadBuf[i] = RD_Byte();			      //读加密存储器的四个字节
	}

	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 *pNewPsw)
{
	unsigned char i,count;
	volatile unsigned char NewPsw[3];
	for(count=0;count<3;count++)
	{
		NewPsw[count] = *pNewPsw;
		pNewPsw++;
	}
	if (RstCard() == 1)							/* 使卡复位*/
		return 1;								/* 如果复位失败返回1 */

	for (i = 0; i < 3; i++)
	{
		WR_Cmd(WRITE_SAFE_MEM,i + 1,NewPsw[i]);		//发送新的密码值
	  Wait_IC();	  		                          //发送操作脉冲
//		NewPsw++;								                    //密码值缓冲区指针加1
	}	
	return 0;
}
/*
*********************************************************************************************************
函数名称:CheckC_Type
功    能:监测卡片类型
输	  入:NewPsw -- 新密码缓冲区,长度为3个字节
输	  出:0 --- 读成功
					1 --- 表示无效卡或者卡损坏
注	  意: 必须校验密码成功后才能修改密码, 否则密码写不进卡中
*********************************************************************************************************
*/
void CheckC_Type(void)
{
  unsigned char i = 0;
	unsigned char ReadBuf[4] = {0};
 
	SDA_OUT();
	
	RST = LOW;
	SCL = LOW;
	Delay_Us(10);
	RST = HIGH;//产生复位时序
	Delay_Us(10);
	SCL = HIGH;
	Delay_Us(20);
	SCL = LOW;
	Delay_Us(10);
	RST = LOW;	  
	
	for(i = 0; i < 4; i++)
	{
		ReadBuf[i] = RD_Byte();
	}

	SCL      = HIGH;
	Delay_Us(5);
	SCL      = LOW;
	SLE_DATA = HIGH;	
	
	if ((ReadBuf[0] == SLE4442ID1) && (ReadBuf[1] == SLE4442ID2) && //SLE4442卡
	    (ReadBuf[2] == SLE4442ID3) && (ReadBuf[3] == SLE4442ID4))
	{	
		WRC_Structure  = SLE4442;

	}
	else
	{
		WRC_Structure = 0xFF;
	}
}


5.程序.h

代码如下:

/*
*********************************************************************************************************

*********************************************************************************************************
*/
#ifndef _IC_H
#define _IC_H
/*
*********************************************************************************************************
头文件
*********************************************************************************************************
*/
#include "stm32f1xx_hal.h"
/*
*********************************************************************************************************
宏定义
*********************************************************************************************************
*/
#define HIGH  1
#define LOW   0

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 

//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 

//IO方向设置
#define SDA_IN()  {GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=0X80000000;}
#define SDA_OUT() {GPIOA->CRH&=0X0FFFFFFF;GPIOA->CRH|=0X30000000;}


#define RST       PAout(11)
#define SCL       PAout(12)
#define SLE_DATA  PAout(15)
/*
*********************************************************************************************************
此处为IC卡保护区00~03单元的值,用于识别卡,这四个字节是SLE4442的标识,
如果  IC卡保护区00~03单元的值 不是这四个字节,表明该卡不是SLE4442卡
或卡已损坏
*********************************************************************************************************
*/

#define SLE4442ID1   0xA2     
#define SLE4442ID2   0x13
#define SLE4442ID3   0x10
#define SLE4442ID4   0x91
/*
*********************************************************************************************************
卡类型编号
*********************************************************************************************************
*/
#define SLE4442      0x77     
#define SLE4428      0x78 
/*
*********************************************************************************************************
指令定义
*********************************************************************************************************
*/

#define READ_MRAM             0x30  //读主存储区
#define WRITE_MRAM            0x38  //写主存储区
#define READ_PRAM             0x34  //读保护存储区 
#define WRITE_PMEM            0x3C  //写保护存储区 
#define READ_PSCR             0x31  //读安全存储器 
#define WRITE_SAFE_MEM        0x39  //写安全存储器 
#define SLE_PSC_CHK           0x33  //校验安全代码 
/*
*********************************************************************************************************
全局定义
*********************************************************************************************************
*/
extern unsigned char WRC_Structure;
extern unsigned char *p_ic_sta;
/*
*********************************************************************************************************
函数声明
*********************************************************************************************************
*/
void ic_Init(void);
unsigned char RstCard(void);
void CheckC_Type(void);
unsigned char CheckPsw(unsigned char *psw);//校验密码
unsigned char ReadPsw(unsigned char *Psw);//读密码
unsigned char ReadCm(unsigned char StarAddr,unsigned char ByteNum,unsigned char *RecBuf);//读主存储区
unsigned char WriteCm(unsigned char StarAdr,unsigned char ByteNum,unsigned char *WriteBuf);//写主存储区
unsigned char WritePm(unsigned char StartAdr,unsigned char ByteNum,unsigned char *WriteBuf);//写保护区
unsigned char ReadPm(unsigned char *RecBuf);//读保护区
unsigned char SetPsw(unsigned char *pNewPsw);//修改密码


#endif



总结

1、通过在main.c中调用即可实现对应功能。
2、IC卡读取数据不需要校验密码,在写入数据需校验密码。
(注意:IC卡初始密码为0xff,0xff,0xff 校验错误三次后将锁死 无法写入数据)
3、PA15作为JTAG调试接口,所以要将其禁用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值