您现在的位置是:首页 > 单片机

sle4442程序(ic卡程序,C语言源代码)

2020-01-28 02:15:48

sle4442程序(ic卡程序,C语言源代码)

//*********************FileName:Main.c*********************//
//*********************Author:[email protected]**********//
//********************Version:1.2*************************//
//******************LastUpdate:2004-11-03*****************//

#include <io8535v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int

//**********定义全局变量*******************//
//查表0    1    2    3    4    5   6    7    8    9    E    F   P   OFF
uchar table[14]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x79,0x71,0x73,0x00};
uchar ICcode[4];//定义IC卡复位时读出的4字节代码;
uchar ICcontent[14];//定义IC卡有效信息;
uchar Money[5];//定义IC卡内金额;
uchar EEEEE[5]={0x79,0x79,0x79,0x79};
uchar FFFFF[5]={0x71,0x71,0x71,0x71};
uchar IC_Flag;//定义IC卡上电标志;
uchar Num_Flag;//数标志;
uchar Add_Flag;//加标志
uchar Sub_Flag;//减标志
uchar Init_Flag;//初始化标志
uchar Repair_Flag;//修卡标志;
uchar Enter_Flag;//确认标志
uchar Point_Flag;//.标志
uchar Key_Flag; //按键标志;

    
//***********IC卡引脚信号处理***************//
void Voice(uchar PD) //Voice=PD^7
{if(PD==1) PORTD|=0x80;//Voice置1
 else      PORTD&=~80; //Voice置0
}

void RST(uchar PD)  //RST=PD^6
{if(PD==1) PORTD|=0x40;//RST置1
 else       PORTD&=~0x40;//RST置0
}

void CLK(uchar PD) //CLK=PD^5
{if(PD==1) PORTD|=0x20;//CLK置1
 else       PORTD&=~0x20;//CLK置0
}

void IO(uchar PD)  //IO=PD^4
{if(PD==1) PORTD|=0x10;//IO置1
 else       PORTD&=~0x10;//IO置0
}
 
void SeTIO(uchar i)//设置IO口属性
{if(i==1) DDRD=0xf0; //IO口输出:1111 0000
 else     DDRD=0xe0; //IO口输如:1110 0000
 PORTD=0x00;//不带上拉电阻;
}

//**********延时函数(Us数量级)*********//
//单周期指令执行时间,执行时间1/8us*分频系数(取8分频则刚好1us);
void DelayUs(uchar i)
{for(;i!=0;i--) 
 NOP();
}

//****************延时函数(Ms数量级)*********//
void DelayMs(uint i)
{uchar j,k;
 for(;i!=0;i--)
    {for(k=0;k<4;k++)
      {for(j=250;j!=0;j--) NOP();}
 }
}

//****************接收数据**************//
uchar ReceiveData(void)
{uchar count;
 uchar value;
 uchar io_value;
 value=0;
 SeTIO(0);//设置IO脚为输入;
 CLK(0);
 //IO=1;
 for(count=0;count<8;count++)
  {value=value>>1;
   CLK(1);
   DelayUs(2);
   io_value=PIND;
   CLK(0);
   DelayUs(2);
   if(io_value&0x10==0x10) value|=0x80;//判断IO脚是否为1
   else value&=0x7f;
  }
 return (value);
}

//********************发送数据************//
void SendData(uchar Xdata) 
{uchar count;
 uchar value;
 SeTIO(1);////设置IO脚为输出;
 value=Xdata;
 for(count=8;count!=0;count--)
  {CLK(0);
  if((Xdata<<(count-1))&0x80) IO(1);
  else IO(0);
  CLK(1);
  DelayUs(2);
  CLK(0);}
}

//****************IC卡复位************************//
void ReseTIC(uchar *Xdata)
{uchar count;
 SetIO(1); //设置IC卡引脚的属性
 RST(0);
 CLK(0);
 IO(1);
 DelayUs(5);
 RST(1);
 DelayUs(5);
 CLK(1);
 DelayUs(5);
 CLK(0);
 DelayUs(5);
 RST(0);
 for(count=4;count!=0;count--)
  {*Xdata=ReceiveData();
  Xdata+=2;}
}

//*******************Start条件****************//
void Start(void)
{SetIO(1);
 CLK(0);
 IO(0);
 DelayUs(2);
 CLK(1);
 IO(1);
 DelayUs(2);
 IO(0);
 CLK(0);
}

//*******************Stop条件****************//
void Stop(void)
{CLK(0);
 IO(0);
 DelayUs(2);
 CLK(1);
 IO(0);
 DelayUs(2);
 IO(1);
 DelayUs(2);
 IO(0);
}

//******************处理过程**************//
void Process(void)
{uint j;
 SetIO(1);//设置IO脚为输出脚
 CLK(0);
 DelayUs(5);
 IO(0);
 for(j=255;j>0;j--)
  {CLK(1);
  DelayUs(5);
  CLK(0);
  DelayUs(5);
 }
 IO(1);
}

//****************说明*********************//
//*********输出模式接口命令,包括读主存储器30H,读保护存储器34H,读安全代码的接口命令31H***********//
//******处理模式数据接口命令,包括写主存储器38H,写保护存储器3CH,写安全代码39H,校验安全代码33H*******//

void Command(uchar Byte1,uchar Byte2,uchar Byte3)
{Start();
 SendData(Byte1);
 SendData(Byte2);
 SendData(Byte3);
 Stop();
}


/**********读主存储器**************/
void ReadMainMemory(uchar addr,uchar *p,uchar N)
{Command(0x30,addr,0xff);
 do{*p=ReceiveData();
    p++;}while(--N);
}

/**********读保护存储器***********/
void ReadProtectMemory(uchar *p)
{uchar i=4;
 Command(0x34,0xff,0xff);
 do{*p=ReceiveData();
    p++;}while(i--);
}

/************写主存储器************/
void WriteMainMemory(uchar Address,uchar Data)
{Command(0x38,Address,Data);
 Process();
}

/**************写保护存储器**********/
void WriteProtectMemory(uchar Address,uchar Data)
{Command(0x3c,Address,Data);
 Process();
}

/**************读安全存储器************/
void ReadSafeMemory(uchar *p)
{uchar i;
 Command(0x31,0xff,0xff);
 for(i=0;i<4;i++)
  {*p=ReceiveData();
  p++;}
}

/*************写安全存储器***************/
void WriteSafeMemory(uchar Address,uchar Data)
{Command(0x39,Address,Data);//Address=0,1,2,3
 Process();
}

/**************校验密码*******************/
uchar VerifyPassword(uchar *p)
{uchar temp[4];//暂存4字节保护密码;
 uchar i;
 ReadSafeMemory(temp);//读安全代码以取得错误计数器
 if((temp[0]&0x07)!=0)
  {if((temp[0]&0x07)==0x07)  i=0x06;
  if((temp[0]&0x07)==0x06)  i=0x04;
     if((temp[0]&0x07)==0x04)  i=0x00;
  WriteSafeMemory(0,i);
  for(i=1;i<4;i++,p++)
   {Command(0x33,i,*p);
   Process();}
     WriteSafeMemory(0,0xff);
  ReadSafeMemory(temp);
  if((temp[0]&0x07)==0x07) return(0x1);
 
 }
 return(0);
}
//*************SLE4442函数结束*****************//

//*************数据变换**********//
void Change(uchar *Source,uchar *Destination,uchar N)
{uchar i,temp;
 for(i=0;i<N;i++)
 {temp=Source[i];
  Destination[i]=temp>>4;
  Destination[2*i+1]=temp&0x0f;}
}

//***********密码错误报警***********************//
void Buzzle_Password(void)
{uchar i;
 for(i=0;i<2;i++)
 {Voice(0);
     DelayMs(1000);
     Voice(1);
     DelayMs(1000);}
}
 
//**********非法卡错误报警*************************//
void Buzzle_Card(void)
{uchar i;
 for(i=0;i<2;i++)
 {Voice(0);
     DelayMs(3000);}
}

//*************余额不足报警**********************//
void Buzzle_Money(void)
{uchar i;
 for(i=0;i<1;i++)
  {Buzzle_Password();
   Buzzle_Card();}
}
 
//*********************读卡函数********************//
//说明:
//函数使用的数组参数用来存放读出的余额值;
//返回值信息:
//0:卡坏!
//1:非法卡(特征值不正确)
//2:非法卡(特征值正确,帐号不正确)
//3:读卡成功!
uchar Read_Card(uchar *p)
{uchar i,tag=0,temp[4];
 ReadSafeMemory(temp);
 if(temp[0]==0x07)
  {ReadMainMemory(32,p,14);//读主存储器14字节:32-35特征码;36-3A帐号;3B-3F余额
   if(p[0]==0x00&&p[1]==0x0f&&p[2]==0xf0&&p[3]==0xff)//特征码:0x00,0x0f,0xf0,0xff
  {for(i=0;i<10;i++)
  if((p[i+4]>=0&&p[i+4]<=9)) tag=tag+1;
  if(tag!=10) return(2);
  else return(3);
 }
   else
    return(1);
  }
 else return(0);
}

//*********************卡初始化函数********************//
//说明:
//函数使用的数组参数用来存放写入的的ID值;
//返回值信息:
//2:初始化失败!
//3:初始化成功!
uchar Initial_Card(uchar *p)
{uchar Psw[3]={0xff,0xff,0xff};
 uchar i,j,temp=0;
 uchar tp[20];
// ResetIC(ICcode);//IC卡复位,读出复位后的厂家信息代码A2131091;
  j=VerifyPassword(Psw);
  WriteMainMemory(32,0x00);//写特征码:
  WriteMainMemory(33,0x0f);
  WriteMainMemory(34,0xf0);
  WriteMainMemory(35,0xff);
  for(i=0;i<5;i++)//写帐号
  WriteMainMemory(36+i,p[i]);//从32+i地址开始写5字节帐号;
  for(i=0;i<5;i++)
  WriteMainMemory(41+i,0);//从32+i地址开始写5字节初始化金额0000.0
  j=Read_Card(tp);
  if(j==3)
   {for(i=0;i<10;i++)
     if(p[i]==tp[i+4]) temp=temp+1;
  }
  if(temp==10)  return(3);
  else return(2);
}

//***************卡修复函数********************//
//说明:
//返回值信息:
//0:修复失败!
//1:修复成功!            
uchar Repair_Card(void)
{uchar Psw[3]={0xff,0xff,0xff};
 uchar i,j,temp;
 i=VerifyPassword(Psw);
 return(i);
}

//********************加卡函数***********//
void Add_Card(uchar *p)
{uchar i;
 uchar temp[14];
 i=Read_Card(temp);
 if(i==3)
  {temp[13]=temp[13]+p[4];
  if(temp[13]>9) {temp[13]=temp[13]-10;temp[12]=temp[12]+1;}
  temp[12]=temp[12]+p[3];
  if(temp[12]>9) {temp[12]=temp[12]-10;temp[11]=temp[11]+1;}
  temp[11]=temp[11]+p[2];
  if(temp[11]>9) {temp[11]=temp[11]-10;temp[10]=temp[10]+1;}
  temp[10]=temp[10]+p[1];
  if(temp[10]>9) {temp[10]=temp[10]-10;temp[9]=temp[9]+1;}
 
  WriteMainMemory(41,temp[9]);
  WriteMainMemory(42,temp[10]);
  WriteMainMemory(43,temp[11]);
  WriteMainMemory(44,temp[12]);
     WriteMainMemory(45,temp[13]);
 }
}

//********************减卡函数***********//
void Sub_Card(uchar *p)
{uchar i,B_Flag;
 uchar temp[14];
 i=Read_Card(temp);
 if((i==3)&&(!(temp[9]<p[0])))
  {if(temp[13]<p[4]) {temp[13]=temp[13]+10-p[4];B_Flag=1;}
  else temp[13]=temp[13]-p[4];
  //以上处理小数点右边的数字;
  if(B_Flag==1)
   {if(temp[12]==0) {temp[12]=9;B_Flag=0;}
    else temp[12]=temp[12]-1;}
  //以上对存在借位情况时对小数点左边第一位进行预处理;
  if(temp[12]<p[3]) {temp[12]=temp[12]+10-p[3];B_Flag=1;}
  else temp[12]=temp[12]-p[3];
  //以上处理小数点小数点左边第一位数字;
   if(B_Flag==1)
   {if(temp[11]==0) {temp[11]=9;B_Flag=0;}
    else temp[11]=temp[11]-1;}
  //以上对存在借位情况时对小数点左边第二位进行预处理;
   if(temp[11]<p[2]) {temp[11]=temp[11]+10-p[2];B_Flag=1;}
   else temp[11]=temp[11]-p[2];
  //以上处理小数点小数点左边第二位数字;
   if(B_Flag==1)
   {if(temp[10]==0) {temp[10]=9;B_Flag=0;}
    else temp[10]=temp[10]-1;}
  //以上对存在借位情况时对小数点左边第三位进行预处理;
   if(temp[10]<p[1]) {temp[10]=temp[10]+10-p[1];B_Flag=1;}
   else temp[10]=temp[10]-p[1];
  //以上处理小数点小数点左边第三位数字;
   if(B_Flag==1)
   {if(temp[9]==0) {temp[9]=0;B_Flag=0;}
    else temp[9]=temp[9]-1;}
  //以上对存在借位情况时对小数点左边第二位进行预处理;
   temp[9]=temp[9]-p[0];
  //以上处理小数点小数点左边第二位数字;
    
  WriteMainMemory(41,temp[9]);
  WriteMainMemory(42,temp[10]);
  WriteMainMemory(43,temp[11]);
  WriteMainMemory(44,temp[12]);
     WriteMainMemory(45,temp[13]);
 }
}
 
//*****************数码管显示函数********************//
void Display(uchar *p)
{uchar sel,i;
 sel=0x01;
 for(i=0;i<6;i++)
   {PORTA=table[p[i]];
    PORTB=sel;
 DelayMs(2);
 sel=sel<<1;}
}
 

//****************键盘扫描函数***********************//
uchar Key_Scan(void)
{uchar sccode,recode;
 PORTC=0xf0;
 if((PINC&0xf0)!=0xf0)
  {DelayMs(10);
  if((PINC&0xf0)!=0xf0)
    {sccode=0xfe;
     while(sccode&0x10!=0x00)
         {PORTC=sccode; //对第一行键盘测试
    if((PINC&0xf0)!=0xf0)
     {recode=(PINC&0xf0)|0x0f;
      return((~sccode)+(~recode));}
    else
     sccode=(sccode<<1)|0x01;
      }
    }
  }
 return(0x00);
}
  
//******************按键处理函数*******************//
void Key_Process(uchar *p)
{uchar temp,value;
 temp=Key_Scan();
 switch(temp)
  {case 0x11:value=9;Num_Flag=1;break;
   case 0x21:value=8;Num_Flag=1;break;
   case 0x41:value=7;Num_Flag=1;break;
   case 0x12:value=6;Num_Flag=1;break;
   case 0x22:value=5;Num_Flag=1;break;
   case 0x42:value=4;Num_Flag=1;break;
   case 0x14:value=3;Num_Flag=1;break;
   case 0x24:value=2;Num_Flag=1;break;
   case 0x44:value=1;Num_Flag=1;break;
   case 0x18:value=0;Num_Flag=1;break;
   case 0x28:Point_Flag=1;break;
   case 0x82:Add_Flag=1;Sub_Flag=0;Key_Flag=1;break;
   case 0x84:Sub_Flag=1;Add_Flag=0;Key_Flag=1;break;
   case 0x48:Repair_Flag=1;Key_Flag=1;break;
   case 0x81:Init_Flag=1;Key_Flag=1;break;
   case 0x88:Enter_Flag=1;Key_Flag=0;break;
   default:     NOP();
  }
 if(Num_Flag==1){p[4]=p[3];p[3]=p[2];p[2]=p[1];p[1]=value;Num_Flag=0;}
 if(Point_Flag==1){p[0]=value;Point_Flag=0;}
 if(Add_Flag==1) {Add_Flag=1;Sub_Flag=0;}
 if(Sub_Flag==1) {Sub_Flag=1;Add_Flag=0;}
 if(Init_Flag==1) {Init_Flag=1;}
 if(Repair_Flag==1) {Repair_Card();Repair_Flag=0;}
 if(Enter_Flag==1)
   {if(Add_Flag==1) {Add_Card(p);Enter_Flag=0;Add_Flag=0;}
    if(Sub_Flag==1) {Sub_Card(p);Enter_Flag=0;Sub_Flag=0;}
 if(Init_Flag==1) {Initial_Card(p);Init_Flag=0;}}
}
  
//***************中断处理********************//
//**********定时器2:16ms中断显示一次*******//
#pragma interrupt_handler TIMER1_INT:9
void TIMER1_INT(void)
{uchar temp[5],i;
 for(i=0;i<5;i++)
   temp[i]=ICcontent[9+i];
 if(IC_Flag==0) Display(EEEEE);
 if(IC_Flag==1) Display(FFFFF);
 if(IC_Flag==3)
   {if(Key_Flag==1)//显示此次操作金额;
      {Money[1]|=0x80;//显示时加上小数点;
    Display(Money);}
 else          //显示卡内余额;
   {temp[4]|=0x80;
    Display(temp);}
   }
}

//*************系统初始化*************//
void Initial_System(void)
{//系统初始化
 //SPL=0x5f;//AT90S8535的堆栈指针指向最高RAM地址;
 //SPH=0x02;
 //IO口初始化;
 DDRA=0xff; //A口输出高电平
 PORTA=0xff;
 DDRB=0xff; //B口输出低电平
 PORTB=0x00;
 DDRC=0x0f; //C口高四位输入(不带上拉电阻)低四位输出0
 PORTC=0xf0;
 DDRD=0xff; //D口输出低电平
 PORTD=0x00;
 //中断系统初始化(定时器1中断)
 SREG=SREG|0x80; //I(SREG^7)全局中断使能置位
 TIMSK=TIMSK|0x40;//TOIE1(TIMSK^2)T/C1溢出中断使能置位
 TIFR=TIFR|0x40;//TOV1(TIFR^2)T/C1溢出中断标志位写"1"清0
 //定时器初始化
 TCCR1B=TCCR1B|0x20;//定时器时钟分频=CLK/8 (1uS计数)
 TCNT1H=0xc1;//需要计数16000=0x3E80次,
 TCNT1L=0x7f;//计数初值0xff-0x3e80=0xc17f;
 //显示系统初始化
 IC_Flag=0;//如果IC卡没有上电,则显示的是8.8.8.8.,否则显示IC卡的内容
}
   
void main(void)
{uchar i,j;
 Initial_System();
 while(IC_Flag==1)
   {DelayMs(5);
    ResetIC(ICcode);
 i=Read_Card(ICcontent);
 if(i==0) {IC_Flag=0; Buzzle_Password();}    //显示EEEE,提示卡坏
    if((i==1)|(i==2)) {IC_Flag=1;Buzzle_Card();} //显示FFFF,提示非法卡
    if(i==3)
   {if(ICcontent[12]<5)
      {IC_Flag=3;Buzzle_Money();}
    else
      {do Key_Process(Money);
    while(Enter_Flag!=0);
    Enter_Flag=0;}
   } 
   }
}

SLE4442/SLE4432 pdf datasheet