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

📄 at88sc102.c

📁 读写AT88sc102/AT88sc1604 IC卡的C源程序。 高可用性
💻 C
📖 第 1 页 / 共 2 页
字号:
    return _C102Write(16, 64, iz);
}


int C102WriteCPZ(int offset, int len, unsigned char *cpz)
{
/*
功能:写代码保护区。写代码保护区为8字节。
输入:offset: 0-7,一般应为偶数,如果offset为奇数,len必须为奇数
      len:     1-8
      cpz:    8字节
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
              -3 = 参数错误,要写入的内容超出存储区; 如果offset为奇数,len必须为奇数
               0 = 正确
*/

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

    if( offset%2 == 1 )
    {//如果offset为奇数,len必须为奇数
        if(len%2 != 1)
            return -3;
    }

    _C102Erase(112 + offset*8, len*8);

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

}


int C102UpdateSC(unsigned char *sc)
{
/*
功能:更新密码。密码为2字节。
输入:sc:2字节
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
               0 = 正确
*/
    _C102Erase(80, 16);
    return _C102Write(80, 16, sc);

}


int C102ReadAZ(int zone, int offset, int len, unsigned char *msg)
{
/*
功能:读应用区1和2中的数据。应用区为64字节。
输入:offset: 0-63
      len:     1-64
输出:msg:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
              -3 = 参数错误,要写入的内容超出存储区
               0 = 正确
*/

    int address;

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

    if(zone == 1)
        address = 176;
    else
        address = 736;

    address = address + offset*8;

    return _C102Read(address, len*8, msg);


}

int C102WriteAZ(int zone, int offset, int len, unsigned char *msg)
{
/*
功能:向应用区1或者2中写数据。应用区为64字节,每个应用区的第0字节的最高2位被强制置为0。
输入:zone:    1-应用区1; 2-应用区2; 
      offset: 0-63, 一般应为偶数,如果offset为奇数,len必须为奇数
      len:     1-64
      msg:     要写的内容
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
              -3 = 参数错误,要写入的内容超出存储区;如果offset为奇数,len必须为奇数
               0 = 正确
*/

    int address;

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

    if( offset%2 == 1 )
    {//如果offset为奇数,len必须为奇数
        if(len%2 != 1)
            return -3;
    }

//将第0字节的最高2位强制置为0。 
    if(offset + len == 0)
        *msg &= 0x3F;   

    if(zone == 1)
        address = 176;
    else
        address = 736;

    address = address + offset*8;

    _C102Erase(address, len*8);

    return _C102Write(address, len*8, msg);

}

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

int _C1604Erase(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+=8)
    {
        _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(TCHP1604);
        _CardSetClock(LOW);
        _CardDelay(TDV); //Tdv=2us

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

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

    }

    return 0;

}

int _C1604Write(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(TCHP1604);
            _CardSetClock(LOW);
            _CardDelay(TDV); //Tdv=2us

        }

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

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

    }

    return 0;

}


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

}

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

    return _C102Read(16, 64, iz);
}

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

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


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


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


    return count;
}

int C1604ReadCPZ(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(104+offset*8, len*8, cpz);
}


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

    return _C102Read(16040, 16, mtz);
}

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

    _C1604Erase(16040, 16);
    return _C1604Write(16040, 16, mtz);
}


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

    return C102CheckSC(sc);

}

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

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

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

    _C1604Erase(104 + offset*8, len*8);

    return _C1604Write(104 + offset*8, len*8, cpz);

}

int C1604UpdateSC(unsigned char *sc)
{
/*
功能:更新密码。密码为2字节。
输入:sc:2字节
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
               0 = 正确
*/
    _C1604Erase(80, 16);
    return _C1604Write(80, 16, sc);

}

int C1604ReadAZ(int zone, int offset, int len, unsigned char *msg)
{
/*
功能:读应用区1-4中的数据。
      应用区1为1195字节: 27--1221。
      应用区2为256字节:  1227--1482。
      应用区3为256字节:  1488--1743。
      应用区4为256字节:  1749--2004。
      总共1963字节
输入:zone:    1-4
      offset: 字节偏移
      len:     字节长度
输出:msg:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
              -3 = 参数错误,要写入的内容超出存储区
               0 = 正确
*/

    int address;
    int total;

    switch(zone)
    {
    case 1:
        address = 216;
        total = 1195;

        break;
    case 2:
        address = 9816;
        total = 256;

        break;
    case 3:
        address = 11904;
        total = 256;

        break;
    case 4:
        address = 13992;
        total = 256;

        break;
    default:
        return -3;

    }

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

    address = address + offset*8;

    return _C102Read(address, len*8, msg);


}

int C1604WriteAZ(int zone, int offset, int len, unsigned char *msg)
{
/*
功能:向应用区1-4中写数据。每个应用区的第0字节的最高2位被强制置为0。
      应用区1为1195字节: 27--1221。
      应用区2为256字节:  1227--1482。
      应用区3为256字节:  1488--1743。
      应用区4为256字节:  1749--2004。
      总共1963字节
输入:zone:    1-4
      offset: 字节偏移
      len:     字节长度
      msg:    要写的内容,字节形式
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
              -3 = 参数错误,要写入的内容超出存储区
*/

    int address;
    int total;

    switch(zone)
    {
    case 1:
        address = 216;
        total = 1195;

        break;
    case 2:
        address = 9816;
        total = 256;

        break;
    case 3:
        address = 11904;
        total = 256;

        break;
    case 4:
        address = 13992;
        total = 256;

        break;
    default:
        return -3;

    }

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

//将第0字节的最高2位强制置为0。 
    if(offset + len == 0)
        *msg &= 0x3F;   

    address = address + offset*8;

    _C1604Erase(address, len*8);

    return _C1604Write(address, len*8, msg);

}

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

int GetBufferLength(int StartBitAddress, int length)
{
    int k;
    int s;

    s = StartBitAddress;

    for(k=0; k<length; k++)
    {
        if(   ((s>=9776)  && (s<9824))
            ||((s>=11864) && (s<11912))
            ||((s>=13952) && (s<14000)) )
        {
            return k;
        }

        s += 8;
    }

    return k;

}

int C1604ReadAZBuffer(int offset, int len, unsigned char *msg)
{
/*
功能:从应用区中读数据。将4个应用区串联起来,向上层提供一个1959字节大小的区域。
      应用区1为1195字节: 27--1221。
      应用区2为256字节:  1227--1482。
      应用区3为256字节:  1488--1743。
      应用区4为256字节:  1749--2004。
      总共1963字节,每个区的第0字节不能使用,因为含有读写控制位。
      可用空间为1963-4=1959字节
输入:offset: 字节偏移
      len:     字节长度
输出:msg:    返回内容,字节形式
      返回值: -1 = 卡不在位; 
              -3 = 参数错误,要写入的内容超出存储区
               0 = 正确
*/

    int i;
    int ret;
    int address;
    int t;
    int wlen=0; //已经读取的字节数

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

    address = 216+8;

    address = address + offset*8;

    for(i=0; i<len; )
    {
        if(   ((address>=9776)  && (address<9824))
            ||((address>=11864) && (address<11912))
            ||((address>=13952) && (address<14000)) )
        {
            address += 8;
        }
        else
        {
            t = GetBufferLength(address, len-wlen);

            ret = _C102Read(address, 8*t, msg);
            if(ret < 0)
                return ret;

            msg += t;
            i += t;
            address += 8*t;
            wlen += t;
        }

    }

    return 0;

}


int C1604WriteAZBuffer(int offset, int len, unsigned char *msg)
{
/*
功能:向应用区中写数据。将4个应用区串联起来,向上层提供一个1959字节大小的区域。
      应用区1为1195字节: 27--1221。
      应用区2为256字节:  1227--1482。
      应用区3为256字节:  1488--1743。
      应用区4为256字节:  1749--2004。
      总共1963字节,每个区的第0字节不能使用,因为含有读写控制位。
      可用空间为1963-4=1959字节
输入:offset: 字节偏移
      len:     字节长度
      msg:    要写的内容,字节形式
输出:返回值: -1 = 卡不在位; 
              -2 = 写入失败,与读出的不一致。
              -3 = 参数错误,要写入的内容超出存储区
               0 = 正确
*/

    int i;
    int ret;
    int address;
    int t;
    int wlen=0; //已经写入的字节数

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

    address = 216+8;

    address = address + offset*8;

    for(i=0; i<len; )
    {
        if(   ((address>=9776)  && (address<9824))
            ||((address>=11864) && (address<11912))
            ||((address>=13952) && (address<14000)) )
        {
            address += 8;
        }
        else
        {

            t = GetBufferLength(address, len-wlen);

            ret = _C1604Erase(address, 8*t);
            if(ret < 0)
                return ret;

            ret = _C1604Write(address, 8*t, msg);
            if(ret < 0)
                return ret;

            msg += t;
            i += t;
            address += 8*t;
            wlen += t;
        }


    }


    return 0;

}

⌨️ 快捷键说明

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