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

📄 at88sc102.c

📁 读写AT88sc102/AT88sc1604 IC卡的C源程序。 高可用性
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************
  江南计算技术研究所 齐传兵 qcb56@126.com
  邮编214083 江苏无锡33信箱342号
*********************************************/

#define  OS_LINUX    1

#if OS_LINUX

#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include <sys/io.h>

#else

#include <dos.h>
#include <mem.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

#define inw(x)     inpw(x)
#define outw(x, y) outpw(y, x)
#define usleep(x)  delay(x/1000)

#endif


#define POWERUP    1
#define POWERDOWN  0
#define HIGH       1
#define LOW        0

#define STATUSW    0x350   //根据自己的硬件定义

#define TCLK       8       //3.3
#define TRH        1       //0.1
#define TDVR       4       //2 max
#define TCH        1       //0.2
#define TCL        1       //0.2
#define TDV        4       //2 max
#define TOH        1       //0
#define TSC        1       //0
#define THC        1       //0.2
#define TCHP       3000    //2000
#define TDS        1       //0.2
#define TDH        1       //0
#define TSPR       5       //2.2
#define THPR       1       //0.2
#define TCHP1604   5000    //5000


/*IC卡操作底层函数说明:
IC卡座的引脚定义示意图如下:
VCC     [C1] [C5]   GND 
RESET   [C2] [C6]   No Use 
CLK     [C3] [C7]   I/O
FUS     [C4] [C8]   PGM
*/

void _CardSetPower(int level)
{
/*
功能:将IC卡读写器Vcc段上电或下电。插入或者拨出IC卡前请先下电。
输入:Level
      当Level=POWERUP,给IC卡读写器上电。
      当Level=POWERDOWN,给IC卡读写器下电。
输出:无
*/

/*根据自己的硬件编写处理过程*/

    usleep(2000);
}


void _CardDataDir(int level)
{
/*
功能:设置MEMORY卡数据传输方向。
输入:Level
      当Level=1,读MEMORY卡。
      当Level=0,写MEMORY卡。
输出:无
*/
/*根据自己的硬件编写处理过程*/

}

void _CardSetReset(int level)
{
/*
功能:置IC卡读写器Reset高或低。
输入:Level
      当Level=1,给IC卡读写器Reset端置高。
      当Level=0,给IC卡读写器Reset端置低。
输出:无
*/
/*根据自己的硬件编写处理过程*/

}


void _CardSetPGM(int level)
{
/*
功能:置IC卡读写器PGM高或低。
输入:Level
      当Level=1,给IC卡读写器PGM置高。
      当Level=0,给IC卡读写器PGM置低。
输出:无
*/
/*根据自己的硬件编写处理过程*/

}

void _CardSetClock(int level)
{
/*
功能:置IC卡读写器Clock高或低。
输入:Level
      当Level=1,给IC卡读写器Clock置高。
      当Level=0,给IC卡读写器Clock置低。
输出:无
*/
/*根据自己的硬件编写处理过程*/
}


int _CardPutIO(int IOData)
{
/*
功能:将数据由IC卡读写器IO端输出。
输入:IOData输出数据,值是0或1。
输出: 0 = 正确
      -1 = 卡不在位
*/
    unsigned int status;

    if(_CardReady() == 0)
        return -1;

    _CardDataDir(LOW);

/*根据自己的硬件编写处理过程*/

    return 0;

}

int _CardReady()
{
/*
功能:查询卡座内是否有卡
输入:无
输出:1--卡座内有卡; 0--座内无卡
*/
    unsigned int status;

/*根据自己的硬件编写处理过程*/

    if(status == 0)
        return 1;
    else
        return 0;

}


int _CardReadIO()
{
/*
功能:读取IC卡读写器IO端数据
输入:无
输出:-1 = 卡不在位
      0  = IC卡输出的数据。
      1  = IC卡输出的数据。
*/
    unsigned int status;

    if(_CardReady() == 0)
        return -1;

    _CardDataDir(HIGH);

/*根据自己的硬件编写处理过程*/

    if(status != 0)
        return 1;
    else
        return 0;

}



void _CardDelay(int usecond)
{
/*
功能:延时。执行usecond个基本延时单位,每个基本延时单位指系统执行一次inw所需的时间(约为1.5us)。。
输入:usecond
输出:无
*/
    int i;

    for(i=0; i<usecond; i++)
        inw(STATUSW);

}

////////////////////////////////////////////////////////////////////////////
/////////ATMEL AT88SC102/AT88SC1604不等分区IC卡基本函数/////////////////////
////////////////////////////////////////////////////////////////////////////

int _C102Reset()
{
/*
功能:如果卡在位,上电并对AT88SC102型MEMORY卡复位。
输入:无
输出:-1 = 卡不在位;0 = 正常
*/
    if(_CardReady() == 0)
        return -1;

    _CardSetType(MEMORYCARD);
    
    
    _CardSetPower(POWERUP);
    _CardSetPGM(LOW);
    _CardSetReset(HIGH);

    _CardSetClock(LOW);

    _CardDelay(TRH);   //需延时0.1微秒Trh

    _CardSetReset(LOW);

    _CardDelay(TDVR);  //2微秒后地址0数据有效 Tdvr

    return 0;

}

void _C102AddsInc(int count)
{
/*
功能:给出count个时钟脉冲,使AT88SC102型IC卡内部地址计数器增加count次。
输入:count
输出:无
*/
    int i;

    for(i=0; i<count; i++)
    {
        _CardSetClock(HIGH);
        _CardDelay(TCH);  // Tch=0.2微秒

        _CardSetClock(LOW);
        _CardDelay(TCL);  //Tcl=0.2微秒

        _CardDelay(TDV);  //Tdv=2微秒
    }

}

int _C102Addressing(int address)
{
/*
功能:如果卡在位,上电,复位,并使AT88SC102型IC卡内部地址计数器为address。
输入:address
输出:-1 = 卡不在位;0 = 正常
*/
    if (_C102Reset() < 0)
        return -1;

    _C102AddsInc(address);

    return 0;
}

int _C102Read(int address, int bitlen, unsigned char *retmsg)
{
/*
功能:从IC卡地址address开始读取bitlen个比特数据。如果address不小于0,先执行上电和复位操作。
输入:address:起始比特地址。 如果小于0, 从当前地址开始; 如果等于-2,读后地址不加并且bitlen应为1
      bitlen   要读的比特长度,应该是8的倍数,否则,最后的比特将放在低字节位(B7--B0)
输出:retmsg: 返回的内容,已经组成字节
      返回值: -1 = 卡不在位;
                0 = 正确
*/

    int i, k;
    int ch;

    if(address >= 0)
    {
        if( _C102Addressing(address) < 0)
            return -1;
    }

    for(i=0, k=0; i<bitlen; )
    {
        ch = _CardReadIO();

        if( ch < 0 )
            return -1;  //卡不在位

        k = (k << 1) | (ch & 1);
        *retmsg = (unsigned char)(k & 0xFF);

        i++;
    
        if(i%8 == 0)
        {
            retmsg++;
            k=0;
        }

        if(address != -2)
            _C102AddsInc(1);

    }

    return 0;

}


int _C102Write(int address, int bitlen, unsigned char *msg)
{
/*
功能:从IC卡地址address开始向IC卡写bitlen个比特数据。如果address不小于0,先执行上电和复位操作。
输入:address:起始比特地址, 如果小于0, 从当前地址开始, 如果等于-2,写后地址不加, bitlen应为1
      bitlen:  要写的比特长度,应该是8的倍数,否则msg应左对齐
      msg:    要写的内容,字节形式
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
               0 = 正确
*/

    int i, k;
    int ch;

    if(address >= 0)
    {
        if( _C102Addressing(address) < 0)
            return -1;
    }

    for(i=0, k=7; i<bitlen; i++)
    {
        ch = *msg;
        ch = ch >> k;
        ch &= 1;

        k--;

        if(k < 0)
        {
            msg++;
            k = 7;
        }


////////////////////////////////////////////////
        if(ch == 0)
        {
            _CardSetClock(LOW);
            _CardSetPGM(HIGH);
            _CardDelay(TDV); //Tdv=2us
            if(_CardPutIO(LOW) < 0)
                return -1;
            _CardDelay(TSPR); //Tspr

            _CardSetClock(HIGH);
            _CardDelay(THPR); //Thpr=0.2us

            _CardSetPGM(LOW);
            usleep(TCHP);
            _CardSetClock(LOW);
            _CardDelay(TDV); //Tdv=2us

        }

        if( _CardReadIO() != ch )
            return -2;

        if(address != -2)
            _C102AddsInc(1);

    }

    return 0;

}


int _C102Erase(int address, int bitlen)
{
/*
功能:从IC卡地址address开始,擦除IC卡中bitlen个比特数据。如果address不小于0,先执行上电和复位操作。
输入:address:起始比特地址, 如果小于0, 从当前地址开始, 如果等于-2,擦除后地址不加, bitlen应为1
      bitlen:  要擦除的比特长度,应该是8的倍数,否则msg应左对齐
      msg:    要写的内容,字节形式
输出:返回值: -1 = 卡不在位; 
              -2 = 擦除失败,与读出的不一致。
               0 = 正确
*/

    int i;

    if(address >= 0)
    {
        if( _C102Addressing(address) < 0)
            return -1;
    }

    for(i=0; i<bitlen; i+=16)
    {
        _CardSetClock(LOW);
        _CardSetPGM(HIGH);
        _CardDelay(TDV); //Tdv=2us
        if(_CardPutIO(HIGH) < 0)
            return -1;
        _CardDelay(TSPR);

        _CardSetClock(HIGH);
        _CardDelay(THPR); //Thpr=0.2us

        _CardSetPGM(LOW);
        usleep(TCHP);
        _CardSetClock(LOW);
        _CardDelay(TDV); //Tdv=2us

        if( _CardReadIO() != 1 )
            return -2;

        if(address != -2)
            _C102AddsInc(16);

    }

    return 0;

}

int _C102BlockErase()
{
/*
功能:执行上电和复位操作,并擦除IC卡中除FZ、MTZ、MFZ外的所有区域。
输入:无
输出:返回值: -1 = 卡不在位; 
              -2 = 擦除失败,与读出的不一致。
               0 = 正确
*/

    int ret;

    ret = _C102Erase(1442, 1);
    usleep(20000);

    return ret;
}

int _C102Compare(int address, int bitlen, unsigned char *msg)
{
/*
功能:从IC卡地址address开始,比较IC卡中bitlen个比特数据。先执行上电和复位操作。
输入:address:起始比特地址
      bitlen:  要比较的比特长度,应该是8的倍数,否则msg应左对齐
      msg:    要比较的内容,字节形式
输出:返回值: -1 = 卡不在位; 
               0 = 正确
*/

    int i, k;
    int ch;
    int ret;

    if( _C102Addressing(address) < 0 )
        return -1;

    for(i=0, k=7; i<bitlen; i++)
    {
        ch = *msg;
        ch = ch >> k;
        ch &= 1;

        k--;

        if(k < 0)
        {
            msg++;
            k = 7;
        }


////////////////////////////////////////////////
        if(ch == 1)
            ret = _CardPutIO(HIGH);
        else
            ret = _CardPutIO(LOW);

        if(ret < 0)
            return -1;

        _CardDelay(TCLK);

        _C102AddsInc(1);

    }

    return 0;
}



/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

int C102ReadFZ(unsigned char *fz)
{ 
/*
功能:读厂商代码。厂商代码为2字节。
输入:无
输出:fz: 厂商代码
      返回值: -1 = 卡不在位; 
               0 = 正确
*/

    return _C102Read(0, 16, fz);
}

int C102ReadIZ(unsigned char *iz)
{ 
/*
功能:读卡商代码。卡商代码为8字节。
输入:无
输出:iz:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
               0 = 正确
*/

    return _C102Read(16, 64, iz);
}

int C102ReadSCAC()
{ 
/*
功能:读密码(或区密码)校验错误计数。
输入:无
输出:返回值: -1  = 卡不在位; 
              0-4 = 允许错误次数,为0表示卡已被锁住
*/

    unsigned char scac;
    unsigned char ch;
    int i, count=0;


    if(_C102Read(96, 8, &scac) < 0)
        return -1;


    scac &= 0xF0;

    for(i=0; i<8; i++)
    {
        ch = (scac >> i) & 1;
        if( ch == 1)
            count++;
    }


    return count;
}

int C102ReadCPZ(int offset, int len, unsigned char *cpz)
{
/*
功能:读代码保护区。代码保护区为8字节。
输入:offset: 0-7
      len:     1-8
输出:cpz:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
              -3 = 参数错误,要写入的内容超出存储区
               0 = 正确
*/

    if(offset+len > 8)
        return -3;

    return _C102Read(112+offset*8, len*8, cpz);

}

int C102ReadMTZ(unsigned char *mtz)
{ 
/*
功能:读测试区。测试区为2字节。
输入:无
输出:mtz:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
               0 = 正确
*/

    return _C102Read(1408, 16, mtz);
}

int C102WriteMTZ(unsigned char *mtz)
{
/*
功能:写测试区。测试区为2字节。
输入:mtz:2字节
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
               0 = 正确
*/

    _C102Erase(1408, 16);
    return _C102Write(1408, 16, mtz);
}

/////////////////////////////////////////////////////////////

int C102CheckSC(unsigned char *sc)
{
/*
功能:比较密码。密码为2字节。
输入:sc:2字节
输出:返回值: 0 = 正确
              其它 = 错误
*/

    int scac;
    int scac1;
    unsigned char ch;

    scac = C102ReadSCAC();
    if(scac == 0)
        return -1;

    if(_C102Compare(80, 16, sc) < 0)
        return -2;

    _C102AddsInc(4-scac);
    ch = 0;
    _C102Write(-2, 1, &ch);
    _C102Read(-2, 1, &ch);
    if(ch != 0)
        return -3;

    _C102Erase(-2, 1);
    _C102Read(-1, 1, &ch);

    if(ch != 1)
        return -4;

    scac1 = C102ReadSCAC();
    if(scac1 != 4)
        return -4;

    return 0;

}

int C102WriteIZ(unsigned char *iz)
{
/*
功能:写卡商代码。卡商代码为8字节。
输入:iz:8字节形式
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
               0 = 正确
*/
    _C102Erase(16, 64);

⌨️ 快捷键说明

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