📄 ecrcard.c
字号:
FLASH_CARD_CLK=0;
#endif //HIGH
_nop_ ( );
_nop_ ( );
FLASH_CARD_CS=1;
sector++;
if(sector>=MAXPAGE) {card_vcc(0);return 1;}
card_addr=0;
array_page_read(PAGE_READ_COM,sector,card_addr);
}
}while(--leng);
#ifdef HIGH
FLASH_CARD_CLK=1;
#else
FLASH_CARD_CLK=0;
#endif
_nop_ ( );
_nop_ ( );
FLASH_CARD_CS=1;
card_vcc(0);
return 0;
}
#endif //FLASH_PAGE
#ifdef FLASH_ARRAY //阵列模式
/**************************************************************/
/*PAGE READ*/
uchar read_flash_card1(ulong addr,uint leng,uchar xdata *str)
{
uint sector,card_addr;
initial_flash_card1();
sector=(addr/0x108)&0xfff;
if(sector>=MAXPAGE) {card_vcc(0);return 1;}
card_addr=(addr%0x108)&0x1ff;
//发送直接阵列方式读FLASH卡主存储区命令及地址
array_page_read(ARRAY_READ_COM,sector,card_addr);
do
{
*str=r_flash_card(); //读1字节FLASH卡主存储区数据
str++;
}while(--leng);
#ifdef HIGH
FLASH_CARD_CLK=1;
#else
FLASH_CARD_CLK=0;
#endif //HIGH
_nop_ ( );
_nop_ ( );
FLASH_CARD_CS=1;
card_vcc(0);
return 0;
}
#endif //FLASH_ARRAY
uchar read_flash_card(ulong addr,uint leng,uchar xdata *str)
{
uchar i;
uint crcnum;
for(i=0;i<3;i++)
{
if(read_flash_card1(addr,leng,str))
{
delayms(250,10); //卡放电时间
continue;
}
crcnum=crcxdata(leng,1,str);
if(read_flash_card1(addr,leng,str))
{
delayms(250,10); //卡放电时间
continue;
}
if(crcnum==crcxdata(leng,1,str)) return 0;
}
return 1;
}
/*******************************************************************/
uchar write_flash_card1(ulong addr,uint leng,uchar xdata *str)
{
uchar card_data;
uint sector,card_addr;
initial_flash_card1();
sector=(addr/0x108)&0xfff;
if(sector>=(MAXPAGE-1)) {card_vcc(0);return 1;}
card_addr=(addr%0x108)&0x1ff;
//FLASH卡主存储区数据读到缓冲区
if(write_card_com(BUFFER_SECTOR_COM,sector)) {card_vcc(0);return 1;}
//发送写缓冲区命令及地址
write_flash_buffer(sector,card_addr);
do{
card_data=*str;
str++;
w_flash_card(card_data); //写1字节到缓冲区
card_addr++;
if((card_addr>=MAXBYTE)&&(leng!=1))
{
#ifdef HIGH
FLASH_CARD_CLK=1;
#else
FLASH_CARD_CLK=0;
#endif
_nop_ ( );
_nop_ ( );
FLASH_CARD_CS=1;
if(read_card_status()) {card_vcc(0);return 1;}
//缓冲区数据写到FLASH卡主存储区
if(write_card_com(BUFFER_RWRITE_COM,sector)) {card_vcc(0);return 1;}
sector++;
if(sector>=(MAXPAGE-1)) {card_vcc(0);return 1;}
card_addr=0;
//FLASH卡主存储区数据读到缓冲区
if(write_card_com(BUFFER_SECTOR_COM,sector)) {card_vcc(0);return 1;}
//发送写缓冲区命令及地址
write_flash_buffer(sector,card_addr);
}
}while(--leng);
#ifdef HIGH
FLASH_CARD_CLK=1;
#else
FLASH_CARD_CLK=0;
#endif
_nop_ ( );
_nop_ ( );
FLASH_CARD_CS=1;
if(read_card_status()) {card_vcc(0);return 1;}
if(write_card_com(BUFFER_RWRITE_COM,sector)) {card_vcc(0);return 1;}
card_vcc(0);
return 0;
}
/*******************************************************************/
uchar write_flash_card(ulong addr,uint leng,uchar xdata *str)
{
uchar i;
uchar xdata buf[1030];
uchar xdata *pointer;
uint length,crcnum;
pointer=str;
while(1)
{
if(leng>1024) length=1024;
else length=leng;
crcnum=crcxdata(length,1,pointer);
for(i=0;i<3;i++)
{
if(write_flash_card1(addr,length,pointer))
{
delayms(250,10); //卡放电时间
continue;
}
if(read_flash_card(addr,length,buf)) return 1;
if(crcnum==crcxdata(length,1,buf)) break;
}
if(i==3) return 1;
pointer+=length;
addr+=length;
leng-=length;
if(!leng) return 0;
}
}
/**************************************************************/
uchar initial_flash_card(void) /* FLASH CARD卡的上电及卡确认*/
{
uchar i,error;
for(i=0;i<3;i++)
{
initial_flash_card1();
// read_flash_card(540408,32,buf);
error=read_card_status();
card_vcc(0);
if(error)
{
delayms(250,10);
continue;
}
if((r_w_byte&0x38)==0x18) return 0;
delayms(250,10);
continue;
}
return 1;
}
#endif //RW_FLASH_CARD
/*CPU CARD*/
uchar rece_cpu_byte(void)
{
uchar i,j=4,m;
uint k;
do
{
m=cpu_d; //等待起始位960 X CPU_D X CPU_TC2
do
{
i=cpu_tc2;
do
{
k=9600;
IC_CARD_IO=1;
do //10us
{
if(!IC_CARD_IO) break;
}while(--k);
if(!IC_CARD_IO) break;
}while(--i);
if(!IC_CARD_IO) break;
}while(--m);
if(!m) return TIMEO; //超时出错
delay_half_etu();
i=8;
do //读出8数据位
{
delay_etu();
if(cpu_t)
{
r_w_byte=r_w_byte>>1;
HBIT=IC_CARD_IO;
_nop_();
}
else
{
r_w_byte=r_w_byte<<1;
LBIT=IC_CARD_IO;
_nop_();
_nop_();
_nop_();
}
}while(--i);
delay_etu(); //接收奇偶校验码
if(!cpu_t) r_w_byte=~r_w_byte;
ACC=r_w_byte;
PSW1=P;
F0=IC_CARD_IO;
delay_half_etu();
if(PSW1)
{
if(F0) return 0;
}
else
{
if(!F0) return 0;
}
delay_half_etu();
IC_CARD_IO=0; //10.5 * etu发送错误信号
delay_etu();
delay_etu();
IC_CARD_IO=1;
}while(--j);
return PARERR;
}
uchar send_cpu_byte(uchar send_data)
{
uchar i,j=4;
do
{
IC_CARD_IO=1;
delay_etu(); //字符间隔时间
delay_etu();
delay_etu();
delay_etu();
IC_CARD_IO=1;
if(!IC_CARD_IO) return PARERR;
if(cpu_tc1&&(cpu_tc1!=0xff))
{
i=cpu_tc1;
do
{
delay_half_etu();
delay_half_etu();
}while(--i);
}
IC_CARD_IO=0; //发送起始位
r_w_byte=send_data;
if(!cpu_t) r_w_byte=~r_w_byte;
i=8;
do
{
delay_etu();
if(cpu_t)
{
IC_CARD_IO=LBIT;
r_w_byte=r_w_byte>>1;
_nop_();
}
else
{
IC_CARD_IO=HBIT;
r_w_byte=r_w_byte<<1;
_nop_();
_nop_();
_nop_();
_nop_();
}
}while(--i);
delay_etu();
ACC=send_data;
_nop_();
_nop_();
IC_CARD_IO=P; //发送奇偶校验位
delay_etu();
r_w_byte=5;
while(--r_w_byte);
IC_CARD_IO=1; //检测错误信号
delay_etu();
r_w_byte=5;
while(--r_w_byte);
if(IC_CARD_IO) return 0; //11 * etu
delay_half_etu();
}while(--j);
return PARERR;
}
uint atr_cpucard(uchar *buf)
{
uchar xdata i,temp,atr_len,error,cpu_tck=0,ti=0;
uchar xdata *p;
uint j=10000;
UNST bw;
atr_len=0;
p=buf;
bw.word=0;
cpu_ta1=0x11,cpu_d=1,cpu_tc1=0,cpu_tc2=10;
EA=0;
select_card_type(CPUCARD);
card_vcc(1);
IC_CARD_RST=0;
do //等待起始位
{
if(!IC_CARD_IO) break;
}while(--j);
IC_CARD_RST=1;
cpu_t=1; //以正向协议传输
if(rece_cpu_byte()) //TS
{
EA=1;
bw.byte.Lo=CPUCARDER; //非CPU卡
return bw.word;
}
if(r_w_byte==0x03) //反向传输
{
cpu_t=0;
r_w_byte=0x3f;
}
else if(r_w_byte!=0x3b) //正向传输
{
EA=1;
bw.byte.Lo=CPUCARDER; //非CPU卡
return bw.word;
}
*p=r_w_byte;
p++;
atr_len++;
error=rece_cpu_byte(); //接收T0
if(error)
{
bw.byte.Lo=error;
EA=1;
return bw.word;
}
*p=r_w_byte;
p++;
atr_len++;
bw.byte.Hi=r_w_byte&0x0f; //保存历史字节数据长度
if((r_w_byte&0x0f)>32) //历史字节数据超长出错
{
EA=1;
bw.byte.Lo=RECEOV;
return bw.word;
}
atr_cpu1:
temp=r_w_byte>>4;
i=4;
do //Td1...Tdi
{
if(temp&0x01)
{
error=rece_cpu_byte();
if(error)
{
bw.byte.Lo=error;
EA=1;
return bw.word;
}
*p=r_w_byte;
p++;
atr_len++;
if(atr_len==32) //数据超长出错
{
EA=1;
bw.byte.Lo=RECEOV;
return bw.word;
}
if(i==4) //TAi
{
if(!ti) cpu_ta1=r_w_byte; //TA1决定接收字符间最大时间
else if(ti==1) cpu_tck=1; //TA2...N表示有TCK校验
}
else if(i==2) //TCi
{
if(!ti) cpu_tc1=r_w_byte; //TC1决定发送字符间最小时间
else if(ti==1) cpu_tc2=r_w_byte; //TC2决定接收字符间最大时间
}
else if(i==1) //TDi---是否有TCK
{
if(r_w_byte&0x0f) cpu_tck=1; //TDi表示有TCK校验
ti++;
goto atr_cpu1;
}
}
temp=temp>>1;
}while(--i);
if(bw.byte.Hi) //有历史数据
{
i=bw.byte.Hi;
bw.byte.Hi+=atr_len;
do //读出历史字节:T1...Tk
{
error=rece_cpu_byte();
if(error)
{
bw.byte.Lo=error;
EA=1;
return bw.word;
}
*p=r_w_byte;
p++;
atr_len++;
if(atr_len==32) //数据超长出错
{
EA=1;
bw.byte.Lo=RECEOV;
return bw.word;
}
}while(--i);
}
else bw.byte.Hi=atr_len;
if(cpu_tck) //有TCK校验
{
error=rece_cpu_byte(); //读出TCK校验值
if(error)
{
bw.byte.Lo=error;
EA=1;
return bw.word;
}
*p=r_w_byte;
p++;
atr_len++;
temp=0; //TCK校验
for(i=1;i<atr_len;i++) temp^=buf[i];
if(temp) //异或校验出错
{
EA=1;
bw.byte.Lo=XORERR;
return bw.word;
}
}
if(!cpu_tc2) cpu_tc2=10;
switch(cpu_ta1&0x0f)
{
case 1:
cpu_d=1;
break;
case 2:
cpu_d=2;
break;
case 3:
cpu_d=4;
break;
case 4:
cpu_d=8;
break;
case 5:
cpu_d=16;
break;
case 6:
cpu_d=32;
break;
case 8:
cpu_d=12;
break;
case 9:
cpu_d=20;
break;
default:
break;
}
EA=1;
return bw.word;
}
uchar Cpu_Apdu(uchar xdata *out_buf,uchar xdata *in_buf)
{
uchar data ins;
uchar i,lc,le,lout,error,send_flag=0;
uchar xdata buf[10];
uchar xdata *out,*in;
uchar xdata **pp;
UNST bw;
EA=0;
le=0;
lc=out_buf[4];
for(i=0;i<5;i++) buf[i]=out_buf[i];
if(!lc) //只读数据
{
le=out_buf[7];
buf[4]=le;
}
lout=le;
ins=buf[1];
pp=(uchar *)&out_buf[5];
out=*pp;
pp=(uchar *)&in_buf[1];
in=*pp;
bw.word=0;
while(1)
{
if(!send_flag) //发送命令
{
send_flag=1;
for(i=0;i<5;i++)
{
error=send_cpu_byte(buf[i]);
if(error) //奇偶错
{
EA=1;
return error;
}
}
}
error=rece_cpu_byte(); //读ACK1
if(error)
{
EA=1;
return error;
}
bw.byte.Hi=r_w_byte;
if(r_w_byte==0x60) continue; //CPU卡忙
if(((r_w_byte&0xf0)==0x60)||((r_w_byte&0xf0)==0x90)) //此时SW1=ACK1
{
error=rece_cpu_byte(); //读SW2
if(error)
{
EA=1;
return error;
}
bw.byte.Lo=r_w_byte;
send_flag=0;
if(bw.byte.Hi==0x61) //lc,le同时有效
{//读取数据长度与文件实际长度不匹配,重发
buf[0]=0;
buf[1]=0xc0;
buf[2]=0;
buf[3]=0;
buf[4]=r_w_byte;
le=r_w_byte;
lout=le;
ins=buf[1];
continue;
}
else if(bw.byte.Hi==0x6c) //没有lc时有效
{//读取剩余数据
buf[4]=r_w_byte;
le=r_w_byte;
lout=le;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -