当前位置:文档之家› at88sc0104c代码

at88sc0104c代码

#include
#include
#define _Nop()_nop_() // 延时1us
sbit SDA=P1^3; // 定义SDA
sbit SCL=P1^2; // 定义SCL
sbit pwr=P3^5; // 供电

unsigned char data GPA[20]; //GPA 单元使用频率高,应直接寻址

unsigned char idata rwdata[0x14];//min=0x04(不读写) max=0x0c(读最大字节数为0x20H,写最大为0x10H)
//前4字节用做命令,数据存放在rwdata[0x04]=>rwdata[0x13]
//参数也可分配成0x0C,但后面一次只能读写8字节数据
//所有从器件解密出的数据和写入器件的数据暂放在此

//******************请填写GC************************************
//GC_TABLE:
unsigned char code GC0[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//GC0
unsigned char code GC1[]={0x00,0x00,0x06,0x09,0x02,0x06,0x16,0x00};//GC1
unsigned char code GC2[]={0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11};//GC2
unsigned char code GC3[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//GC3

//******************请填写PASSWORD************************************
//PASSWORD_TABLE:
unsigned char code PW_WRITE0[]={0x80,0x00,0x00};//WRITE PASSWORD 0
unsigned char code PW_READ0[]= {0x00,0x00,0x00};//READ PASSWORD 0
unsigned char code PW_WRITE1[]={0x11,0x00,0x11};//WRITE PASSWORD 1
unsigned char code PW_READ1[]= {0x00,0x00,0x00};//READ PASSWORD 1
unsigned char code PW_WRITE2[]={0x00,0x00,0x00};//WRITE PASSWORD 2
unsigned char code PW_READ2[]= {0x00,0x00,0x00};//READ PASSWORD 2
unsigned char code PW_WRITE3[]={0x00,0x00,0x00};//WRITE PASSWORD 3
unsigned char code PW_READ3[]= {0x00,0x00,0x00};//READ PASSWORD 3
unsigned char code PW_WRITE4[]={0x22,0x22,0x22};//WRITE PASSWORD 4
unsigned char code PW_READ4[]= {0x22,0x22,0x22};//READ PASSWORD 4
unsigned char code PW_WRITE5[]={0x00,0x00,0x00};//WRITE PASSWORD 5
unsigned char code PW_READ5[]= {0x00,0x00,0x00};//READ PASSWORD 5
unsigned char code PW_WRITE6[]={0x00,0x00,0x00};//WRITE PASSWORD 6
unsigned char code PW_READ6[]= {0x00,0x00,0x00};//READ PASSWORD 6
unsigned char code PW_WRITE7[]={0xdd,0x42,0x97};//WRITE PASSWORD 7
unsigned char code PW_READ7[]= {0x00,0x00,0x00};//READ PASSWORD 7


void SMSTART(void);//功能:启动I2C
void SMSTOP(void); //功能:停止I2C
void delay_ms(); //功能:延时1ms

void Wait_For_AckPolling(void);
//功能:检查所发送的命令是否已被执行
//只有当AckPolling_return=1或bytecounter=0时,该程序才退出

void GPA_CLOCK(unsigned char Datain,unsigned char times);
//GPA函数
//入口:Data_in
//出口:GPA[0]:GPA_byte
//参

数:times GPA函数计算的次数

void read(rd);
//功能:对at88scxx I2C读操作函数
//本程序中以read(rwdata)调用;
//入口:rwdata数组
//出口:rwdata数组
//rd数组长度可改
//cmd_send_counter发送命令次数,超出8次,本函数退出,并认为I2C线路上无器件

void write(SDATA);
//功能:对at88scxx I2C写操作函数
//本程序中以write(rwdata)调用;
//入口:rwdata数组
//出口:rwdata数组
//rd数组长度可改
//cmd_send_counter发送命令次数,超出8次,本函数退出,并认为I2C线路上无器件


unsigned char AUTHENTICATION(unsigned char GC_select);
//双向认证函数
//入口:GC_select:选择密钥套数
//出口:AAC: 认证结果
//过程:
//1.从器件读出CIx,产生随机数Q0,计算密钥;计算出Q1,将Q0、Q1发送给器件,计算出新的CIx,SKx
//2.用读回的CIx与计算出的CIx比较
//3.用计算出的SKx替代GCx,重复1过程
//AAC:认证错误计数器.AAC!=0xff表示双向认证未通过或无器件
//需产生随机数则应在程序里修改


unsigned char verify_write_password(unsigned char pw_select);
//校验写密码组主函数,正确校验了写密码后开放读写
//pw_select:密码套数选择
//PAC:密码校验错误计数器.PAC!=0xff表示认证未通过或无器件

void set_user_zone(unsigned char zone);
//选择用户区
//zone:用户区序号

void read_user_zone(unsigned char idata rd_high_addr,unsigned char idata rd_low_addr,unsigned char idata rd_number);
//读出用户区密文数据,并解出明文数据
//rd_high_addr 用户区高字节地址
//rd_low_addr 用户区低字节地址
//rd_number 读取密文数据及解出明文数据的个数
//解密出的明文数据存放在rwdata[0x04]=>rwdata[0x13]

void read_config_zone(unsigned char idata rd_high_addr,unsigned char idata rd_low_addr,unsigned char idata rd_number);
//当rd_low_addr往后不应滚动到0xb0
//如想读 0xb0
void encrypto_data(unsigned char encryptodatanumber);
//对明文数据进行加密
//encryptodatanumber加密数据的个数
//需加密的明文数据存放在 r

wdata[4]至rwdata[0x13]

void write_user_zone(unsigned char wr_high_addr,unsigned char wr_low_addr,unsigned char wr_number);
//功能:把已加密了的密文数据写到器件
//wr_high_addr 用户区高字节地址
//wr_low_addr 用户区低字节地址
//wr_number 写入数据的个数
//将存放在 rwdata[4]至rwdata[0x13]明文数据写入器件

void send_checksum();
//功能:发送校验和到器件(以密文形式写入数据后,需发送校验和)

void write_config_zone(unsigned char wr_high_addr,unsigned char wr_low_addr,unsigned char wr_number);
//当rd_low_addr往后不应滚动到0xb0
//如想读 0xb0//熔丝断后不可写

//****************明文读写部分******************************
unsigned char verify_sc_plaintext(unsigned char sc_first_byte,unsigned char sc_second_byte,unsigned char sc_third_byte);
//功能:校验安全密码(传输密码),该密码位置在write7_password
//在器件熔丝未断前,校验安全密码成功后,可以对器件配置区,用户区的随意读写
//sc_firsr_byte 密码的第1个字节数据
//sc_second_byte 密码的第2个字节数据
//sc_third_byte 密码的第3个字节数据
//如verify_sc_plaintext(0xDD,0x42,0x97)
//0xDD,0x42,0x97分别为密码的第123个字节数据

void set_user_zone_plaintext(unsigned char zonep);
//选择用户区(明文)
//zonep:用户区序号

void read_paintext(unsigned char rd_cmd,unsigned char A1,unsigned char A2,unsigned char N);
//读操作(明文)
//rd_cmd:0xb2 读用户区 /0xb6 读配置区 /0xb6 0x01 0x00 0x01 读熔丝
//A1 :高字节地址
//A2 :地字节地址
//N :读取数据个数

void write_paintext(unsigned char wr_cmd,unsigned char A1,unsigned char A2,unsigned char N);
//写操作(明文)
//rd_cmd:0xb0 写用户区 /0xb4 写配置区 /0xb4 0x01 ID 0x00 写熔丝
//A1 :高字节地址
//A2 :地字节地址
//N :写数据个数
//注意:烧断熔丝时只能从ID=0x06=>0x04=>0x00


////////////////////////////////////////
void main()
{
unsigned char data j;
unsigned char idata PAC_WR7;//PAC_WR7=0xFF则表明校验SC正确
unsigned char idata AAC; //AAC=0xFF则表明校验GCx正确
unsigned char idata PAC; //PAC=0xFF则表明校验PWx正确
pwr=0;

//上电
AAC=0;
PAC=0;
//goto MTZ_Test;
//goto Set_AAC_PAC_FF;
//goto RW_Config_User_Zone_Plaintext;
//goto RW_User_Zone_Encryptoed;
//goto RW_Config_Zone_Encryptoed;
////////////////////密文读写部分////////////////////////////////////////
RW_User_Zone_Encryptoed:

AAC=AUTHENTICATION(0x02); //0x02使用02套密钥/
PAC=verify_write_password(0x04);//0x04使用04套密码,只读可用verify_read_password(pw_select)
set_user_zone(0x00); //0x00进入00H用户区
read_user_zone(0x00,0x00,0x10); //解密出的明文数据存放在rwdata[0x04]=>rwdata[0x13]
//read_user_zone(rd_high_addr,rd_low_addr,rd_number)
//rd_high_addr:对于0104恒为0x00
//rd_low_addr:读0104用户区的首地址
//rd_number:读出的数据字节数
//如read_user_zone(0x00,0x00,0x10)则读解0104下0x00H-0x0fH单元
read_user_zone(0x00,0x10,0x10);

for(j=0x04;j<0x0c;j++)
{rwdata[j]=0x85;}
for(j=0x0c;j<0x14;j++)
{rwdata[j]=0x66;} //明文数据存放在 rwdata[4]至rwdata[0x13]
write_user_zone(0x00,0x00,0x10);//write_user_zone(wr_high_addr,wr_low_addr,wr_number)

for(j=0x04;j<0x0c;j++)
{rwdata[j]=0x28;}
for(j=0x0c;j<0x14;j++)
{rwdata[j]=0x66;} //明文数据存放在 rwdata[4]至rwdata[0x13]
write_user_zone(0x00,0x10,0x10);//write_user_zone(wr_high_addr,wr_low_addr,wr_number)
//wr_high_addr:对于0104恒为0x00
//wr_number:写入0104的数据字节数
//如write_user_zone(0x00,0x00,0x10)则把数据写到0104下0x00H-0x0fH单元

set_user_zone(0x00); //再调用命令操作防止写数据掉电丢失
pwr=1; //芯片下电,释放SDA SCL,RAM单元以做其他用
while(1);

////////////////密文方式读写配置区///////////////////////////////////////////
RW_Config_Zone_Encryptoed:

AAC=AUTHENTICATION(0x02); //0x02使用02套密钥/
PAC=verify_write_password(0x07);//0x07使用07套密码,开放所有权限
for(j=0x04;j<0x0c;j++)
{rwdata[j]=0x28;}
for(j=0x0c;j<0x14;j++)
{rwdata[j]=0x66;}
write_config_zone(0x00,0x40,0x10);//熔丝断后不可写
read_config_zone(0x00,0x40,0x10);

for(j=0x04;j<0x0c;j++)
{rwdata[j]=0x18;}
for(j=0x0c;j<0x14;j++)
{rwdata[j]=0x16;}
write_config_zone(0x00,0xb0,0x10); //low_addr+ wr_number不应超过B0,若要读写 0xb0后应另起一行
read_config_zone(0x00,0xb0,0x10);

for(j=0x04;j<0x0c;j++)
{rwdata[j]=0x58;}
for(j=0x0c;j<0x14;j++)
{rwdata[j]=0x56;}
write_config_zone(0x00,0xb0,0x10); //low_addr+ wr_number不应超

过B0,若要读写 0xb0后应另起一行
read_config_zone(0x00,0xb0,0x10);

while(1);


//////////////////明文读写部分,可执行F1算法/////////////////////////////
/////////////////////////////////////////////////////////////
MTZ_Test:
rwdata[4]=0x88;
rwdata[5]=0x66; //明文写
write_paintext(0xb4,0x00,0x0a,0x02); //write_paintext(0xb0 或 0xb4,A1,A2,N)
read_paintext(0xb6,0x00,0x0a,0x02); //明文读
//读回rwdata[4]=0x85;rwdata[5]=0x66;则表明通讯测试成功
while(1);

///////////////////////////////////////////////////////////
Set_AAC_PAC_FF://恢复设置 ACC PAC
rwdata[4]=0xff;
write_paintext(0xb4,0x00,0x70,0x04); //write_paintext(0xb0 或 0xb4,A1,A2,N)
read_paintext(0xb6,0x00,0x70,0x10); //明文读
rwdata[4]=0xff;
write_paintext(0xb4,0x00,0xd0,0x01); //write_paintext(0xb0 或 0xb4,A1,A2,N)
read_paintext(0xb6,0x00,0xd0,0x01); //明文读
while(1);

////////////////////////////////////////////////////////////
RW_Config_User_Zone_Plaintext://明文读写配置区或用户区或熔丝
PAC_WR7=verify_sc_plaintext(0xDD,0x42,0x97);//校验SC
set_user_zone_plaintext(0x03); //选区
read_paintext(0xb2,0x00,0x00,0x10); //明文读
//read_paintext(0xb2 或 0xb6,A1,A2,N)
rwdata[4]=0x85;
rwdata[5]=0x66; //明文写
rwdata[6]=0x28;
rwdata[7]=0x66;
write_paintext(0xb0,0x00,0x00,0x04); //write_paintext(0xb0 或 0xb4,A1,A2,N)
//如以明文写用户区,则AR PR应为0xFF
read_paintext(0xb2,0x00,0x00,0x10); //明文读
while(1);

}

//******************delay_ms*********************************
//功能:延时1ms
//*****************************************************************
void delay_ms()
{
unsigned char idata j;
for(j=0x00;j<255;j++)
{
_Nop();_Nop();_Nop();
}
}

//***********************SMSTART***********************************
//功能:启动I2C
//*****************************************************************
void SMSTART(void)
{
SDA=1;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();SCL=0;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();SCL=0;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();SCL=0;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();SCL=0;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();SCL=0;_Nop();_Nop();_Nop();//先打出5个CLK

SCL=1;_Nop();_Nop();_Nop();
SDA=1;_Nop();_Nop();_Nop();
SDA=0;_Nop();_Nop();_Nop();
SCL=0;_Nop();_Nop();_Nop();
}

//************************SMSTOP***********************************
//功

能:停止I2C
//*****************************************************************
void SMSTOP(void)
{
SCL=1;_Nop();_Nop();_Nop();
SDA=0;_Nop();_Nop();_Nop();
SDA=1;_Nop();_Nop();_Nop();
SCL=0;_Nop();_Nop();_Nop();
}

//************************AckPolling*******************************
//功能:检查所发送的命令是否已被执行
//只有当AckPolling_return=1或bytecounter=0时,该程序才退出
//*****************************************************************
void Wait_For_AckPolling(void)
{
unsigned char AckPolling_return;
unsigned char temp, bitcounter;
unsigned char bytecounter;

SMSTART();
temp=0xb6;
bytecounter=0xff;//如CPU速度过快须加大其值
AckPolling_return=0;

do{
for(bitcounter=0;bitcounter<8;bitcounter++)
{
if ((temp&0x80)==0x80)
{SDA=1;}
else
{SDA=0;}
_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();
SCL=0;_Nop();_Nop();
temp=temp<<1;
}

SDA=1;_Nop();_Nop();
SCL=1;_Nop();_Nop();
bytecounter--;

if(SDA==0)
{SCL=0;AckPolling_return=1;}
else
{SCL=0;AckPolling_return=0;SMSTART();temp=0xb6;}

if(AckPolling_return==1)
{break;}

}while(bytecounter>0);

SMSTOP();
}

//*********************GPA_CLOCK************************************
//GPA函数
//入口:Data_in
//出口:GPA[0]:GPA_byte
//参数:times GPA函数计算的次数
//*****************************************************************
void GPA_CLOCK(unsigned char Datain,unsigned char times)
{
unsigned char t;
unsigned char d;
unsigned char idata din_gpa;
unsigned char idata Ri;
unsigned char idata R_Sum;
unsigned char idata Si;
unsigned char idata S_Sum;
unsigned char idata Ti;
unsigned char idata T_Sum;

for(t=0x00;t{
din_gpa=Datain ^ GPA[0];
Ri= din_gpa&0x1f;
Si= ((din_gpa&0x0f)<<3)+((din_gpa&0xe0)>>5);
Ti=(din_gpa&0xf8)>>3;
//r元素
if(((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4))>31)
{R_Sum=((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4))-31;}
else
{R_Sum=((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4));}

GPA[1]=GPA[2];
GPA[2]=GPA[3];
GPA[3]=GPA[4];
GPA[4]=GPA[5]^Ri;
GPA[5]=GPA[6];
GPA[6]=GPA[7];
GPA[7]=R_Sum;
//s元素
if ((GPA[9]+((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) )>127)
{S_Sum=( (GPA[9]) + ((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) )-127;}
else
{S_Sum= (GPA[9]) + ((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) ;}

GPA[8]=GPA[9];
GPA[9]=Si^GPA[10];
GPA[10]=GPA[11];
GPA[11]=GPA[12];
GPA[12]=GPA[13];
GPA[13]=GPA[14];

GPA[14]=S_Sum;
//t元素
if ((GPA[15]+GPA[17])> 31)
{T_Sum=GPA[15]+GPA[17]-31;}
else
{T_Sum=GPA[15]+GPA[17];}

GPA[15]=GPA[16];
GPA[16]=GPA[17];
GPA[17]=GPA[18]^Ti;
GPA[18]=GPA[19];
GPA[19]=T_Sum;
///Output
if((GPA[14]&0x01)==0)
{d=((GPA[7]^GPA[3])&0x01);}
else
{d=((GPA[19]^GPA[16])&0x01);}

if((GPA[14]&0x02)==0)
{d=d+((GPA[7]^GPA[3])&0x02);}
else
{d=d+((GPA[19]^GPA[16])&0x02);}

if((GPA[14]&0x04)==0)
{d=d+((GPA[7]^GPA[3])&0x04);}
else
{d=d+((GPA[19]^GPA[16])&0x04);}

if((GPA[14]&0x08)==0)
{d=d+((GPA[7]^GPA[3])&0x08);}
else
{d=d+((GPA[19]^GPA[16])&0x08);}

GPA[0]= ( (((GPA[0])&0x0f)<<4) +d); //GPA出口
}
}
//***********************read*************************
//功能:对at88scxx读操作函数
//本程序中以read(rwdata)调用;
//入口:rwdata数组
//出口:rwdata数组
//rd数组长度可改
//cmd_send_counter发送命令次数,超出8次,本函数退出,并认为I2C线路上无器件
//*****************************************************************
void read(rd)//
unsigned char idata rd[0x20];
{
unsigned char bitcounter;
unsigned char temp;
unsigned char cmd_send_counter;
unsigned char bytecounter;
temp=rd[0];
bytecounter=0;
cmd_send_counter=0;
SMSTART();

do{
for(bitcounter=0;bitcounter<8;bitcounter++)
{
if ((temp&0x80)==0x80)
{SDA=1;}
else
{SDA=0;}
_Nop();_Nop();
SCL=1;_Nop();_Nop();
SCL=0;temp=temp<<1;
}

SDA=1;_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();_Nop();

if(SDA==0)
{SCL=0;bytecounter++;temp=rd[bytecounter];}
else
{SCL=0;SMSTART();temp=rd[0];bytecounter=0;cmd_send_counter++;}

if(cmd_send_counter>8)
{bytecounter=4;}

}while(bytecounter<4);

//rev byte
SDA=1;
for(bytecounter=0;bytecounter{
for(bitcounter=0;bitcounter<8;bitcounter++)
{
SCL=1;_Nop();_Nop();

if (SDA==1)
{temp=temp|0x01;}
else
{temp=(temp&0xfe);}

if(bitcounter<7)
{temp=temp<<1;}
else
{_Nop();}

SCL=0;_Nop();_Nop();
}
SDA=0;_Nop();_Nop();
SCL=1;_Nop();_Nop();
SCL=0;_Nop();_Nop();
SDA=1;_Nop();
rd[bytecounter+4]=temp;
}

SMSTOP();
}
//************************write***************************************
//功能:对at88scxx写操作函数
//本程序中以write(rwdata)调用;

//入口:rwdata数组
//出口:rwdata数组
//rd数组长度可改
//cmd_send_counter发送命令次数,超出8次,本函数退出,并认为I2C线路上无器件
//*****************************************************************
void write(SDATA)
unsigned char idata SDATA[0X14];
{
unsigned char bitcounter;
unsigned char temp;
unsigned char bytecounter;
unsigned char cmd_send_counter;
temp=SDATA[0];
bytecounter=0;
cmd_send_counter=0;
SMSTART();

do{
for(bitcounter=0;bitcounter<8;bitcounter++)
{
if ((temp&0x80)==0x80)
{SDA=1;}
else
{SDA=0;}

_Nop();_Nop();_Nop();
SCL=1;_Nop();_Nop();
SCL=0;_Nop();_Nop();
temp=temp<<1;
}

SDA=1;_Nop();_Nop();
SCL=1;_Nop();_Nop();

if(SDA==0)
{SCL=0;bytecounter++;temp=SDATA[bytecounter];}
else
{SCL=0;SMSTART();temp=SDATA[0];bytecounter=0;cmd_send_counter++;}

if(cmd_send_counter>8)
{bytecounter=SDATA[3]+4;}

}while(bytecounter
SMSTOP();
}
//*****************************AUTHENTICATION*****************************
//双向认证函数
//入口:GC_select:选择密钥套数
//出口:AAC: 认证结果
//过程:
//1.从器件读出CIx,产生随机数Q0,计算密钥;计算出Q1,将Q0、Q1发送给器件,计算出新的CIx,SKx
//2.用读回的CIx与计算出的CIx比较
//3.用计算出的SKx替代GCx,重复1过程
//AAC:认证错误计数器.AAC!=0xff表示双向认证未通过或无器件
//需产生随机数则应在程序里修改
//************************************************************************
unsigned char AUTHENTICATION(unsigned char GC_select)
{
unsigned char idata SK[8]; //会话密钥
unsigned char idata Q_CH[0x14];//发送14H字节载体
unsigned char j;

for(j=0;j<=19;j++)
{GPA[j]=0x00;}//初始化GPA单元

Q_CH[0]=0xb6;
Q_CH[1]=0x00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
read(Q_CH);

for(j=0;j<8;j++)
{Q_CH[j+12]=Q_CH[j+4];}//CI

for(j=0;j<8;j++)
{Q_CH[j+4]=0xAA;} //此处可改随机数

for(j=0;j<4;j++)
{
GPA_CLOCK(Q_CH[12+2*j],0x03);
GPA_CLOCK(Q_CH[12+2*j+1],0x03);
GPA_CLOCK(Q_CH[4+j],0x01);
}

if ((GC_select&0x0f)==0x00)
for(j=0;j<8;j++)
{Q_CH[12+j]=GC0[j];}
else if ((GC_select&0x0f)==0x01)
for(j=0;j<8;j++)
{Q_CH[12+j]=GC1[j];}
else if ((GC_select&0x0f)==0x02)
for(j=0;j<8;j++)
{Q_CH[12+j]=GC2[j];}
else
for(j=0;j<8;j++)
{Q_CH[12+j]=GC3[j];}

for(j=0;j<4;j++)
{
GPA_CLOCK(Q_CH[12+2*j],0x03);
GPA_CLOCK(Q_CH[12+2*j+1],0x03);
GPA_CLOCK(Q_CH[8+j],0x01);
}

GPA_CLOCK(0x00

,0x06);
Q_CH[12]=GPA[0];
for(j=1;j<8;j++)
{
GPA_CLOCK(0x00,0x07);
Q_CH[12+j]=GPA[0];
}

Q_CH[0]=0xb8;//send ch
Q_CH[2]=0x00;
Q_CH[3]=0x10;
Q_CH[1]=GC_select;
write(Q_CH);
Wait_For_AckPolling();

//new ci
Q_CH[12]=0xFF;
for(j=1;j<8;j++)
{
GPA_CLOCK(0x00,0x02);
Q_CH[12+j]=GPA[0];
}
//new sk
for(j=0;j<8;j++)
{
GPA_CLOCK(0x00,0x02);
SK[j]=GPA[0];
}
GPA_CLOCK(0x00,0x03);

//比较CI值是否一致
Q_CH[0]=0XB6;
Q_CH[1]=0X00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
read(Q_CH);
Wait_For_AckPolling();
if (Q_CH[4]!=0xff)
{goto Aut_Report;}

for(j=0;j<8;j++)
{
if(Q_CH[4+j]!= Q_CH[12+j])
{goto Aut_Report;}
}

GPA_CLOCK(0x00,0x05);
GPA_CLOCK(Q_CH[2],0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(0x08,0x01);
for(j=0;j<8;j++)
{
GPA_CLOCK(Q_CH[4+j],0x01);
GPA_CLOCK(0x00,0x05);
}
//******************crypto_Authentication*************************
//以会话密钥再认证一次
//*****************************************************************
for(j=0;j<=19;j++)
{GPA[j]=0x00;}

for(j=0;j<8;j++)
{Q_CH[j+4]=0xAA;} //此处可改随机数

for(j=0;j<4;j++)
{
GPA_CLOCK(Q_CH[12+2*j],0x03);
GPA_CLOCK(Q_CH[12+2*j+1],0x03);
GPA_CLOCK(Q_CH[4+j],0x01);
}

for(j=0;j<4;j++)
{
GPA_CLOCK(SK[2*j],0x03);
GPA_CLOCK(SK[2*j+1],0x03);
GPA_CLOCK(Q_CH[8+j],0x01);
}

GPA_CLOCK(0x00,0x06);
Q_CH[12]=GPA[0];
for(j=1;j<8;j++)
{
GPA_CLOCK(0x00,0x07);
Q_CH[12+j]=GPA[0];
}

Q_CH[0]=0xb8;
Q_CH[1]=GC_select+0x10;
Q_CH[2]=0x00;
Q_CH[3]=0x10;
write(Q_CH);
Wait_For_AckPolling();

//new ci
Q_CH[12]=0xFF;
for(j=1;j<8;j++)
{
GPA_CLOCK(0x00,0x02);
Q_CH[12+j]=GPA[0];
}
//new sk
for(j=0;j<8;j++)
{
GPA_CLOCK(0x00,0x02);
SK[j]=GPA[0];
}
GPA_CLOCK(0x00,0x03);

//比较CI值是否一致
Q_CH[0]=0XB6;
Q_CH[1]=0X00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
read(Q_CH);
Wait_For_AckPolling();
if (Q_CH[4]!=0xff)
{goto Aut_Report;}

for(j=0;j<8;j++)
{
if(Q_CH[4+j]!= Q_CH[12+j])
{goto Aut_Report;}
}

GPA_CLOCK(0x00,0x05);
GPA_CLOCK(Q_CH[2],0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(0x08,0x01);
for(j=0;j<8;j++)
{
GPA_CLOCK(Q_CH[4+j],0x01);
GPA_CLOCK(0x00,0x05);
}

Aut_Report:
return Q_CH[4];
}

//******************verify_wr_pw********************************
//校验写密码组主函数,正确校验了写密码后开放读写
//pw_select:密码套数选择

//PAC:密码校验错误计数器.PAC!=0xff表示认证未通过或无器件
//****************************************************************
unsigned char verify_write_password(unsigned char pw_select)
{
unsigned char j;
unsigned char idata pw[7];

if ((pw_select&0x0f)==0x00)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE0[j];}
else if ((pw_select&0x0f)==0x01)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE1[j];}
else if ((pw_select&0x0f)==0x02)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE2[j];}
else if ((pw_select&0x0f)==0x03)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE3[j];}
else if ((pw_select&0x0f)==0x04)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE4[j];}
else if ((pw_select&0x0f)==0x05)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE5[j];}
else if ((pw_select&0x0f)==0x06)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE6[j];}
else
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE7[j];}

for(j=0;j<3;j++)
{
GPA_CLOCK(pw[4+j],0x05);
pw[4+j]=GPA[0];
}
pw[0]=0xba;
pw[1]=pw_select&0x0f;
pw[2]=0x00;
pw[3]=0x03;
write(pw);
Wait_For_AckPolling();

pw[0]=0XB6;
pw[1]=0X00;
pw[2]=pw_select&0x0f;
pw[2]=pw[2]*0x08;
pw[2]=pw[2]+0xb0;
pw[3]=0x01;
read(pw);
Wait_For_AckPolling();

GPA_CLOCK(0x00,0x05);
GPA_CLOCK(pw[2],0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(0x01,0x01);
pw[4]=pw[4]^GPA[0];
GPA_CLOCK(pw[4],0x01);
GPA_CLOCK(0x00,0x05);

return pw[4];
}

//******************verify_read_pw********************************
//可以用本函数校验读密码,但只开放读权限
//校验读密码组主函数,正确校验了读密码后只开放读
//pw_select:密码套数选择
//PAC:密码校验错误计数器.PAC=0xff表示认证通过,PAC!=0xff表示认证未通过或无器件
//****************************************************************
/*unsigned char verify_read_password(unsigned char pw_select)
{
unsigned char j;
unsigned char idata pw[7];
if ((pw_select&0x0f)==0x00)
{for(j=0;j<3;j++)
{pw[4+j]=PW_READ0[j];}}//{*(p+42+j)=PW_WRITE0[j];}}
else if ((pw_select&0x0f)==0x01)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ1[j];}
else if ((pw_select&0x0f)==0x02)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ2[j];}
else if ((pw_select&0x0f)==0x03)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ3[j];}
else if ((pw_select&0x0f)==0x04)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ4[j];}
else if ((pw_select&0x0f)==0x05)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ5[j];}
else if ((pw_select&0x0f)==0x06)
for(j=0;j<3;j++)
{pw[4+j]=PW_READ6[j];}
else
for(j=0;j<3;j++)
{pw[4+j]=PW_READ7[j];}

for(j=0;j<3;j++)
{
GPA_CLOCK(pw[4+j],0x05);//GPA[0]=pw[4+j];GPA_CLOCK(0x05);
pw[4+j]=GPA[0];//*(p+42

+j)=*(p+11);
}
pw[0]=0xba;//*(p+38)=0xba; //
pw[1]=pw_select&0x0f;//*(p+39)=*(p+1)&0x0f;
pw[1]=pw[1]+0x10;
pw[2]=0x00;//*(p+40)=0x00;
pw[3]=0x03;//*(p+41)=0x03;
write(pw);
delay_ms(); delay_ms();delay_ms();

pw[0]=0XB6;
pw[1]=0X00;
pw[2]=pw_select&0x0f;
pw[2]=pw[2]*0x08;
pw[2]=pw[2]+0xb4;
pw[3]=0x01;
read(pw);

GPA_CLOCK(0x00,0x05);//GPA[0]=0x00;GPA_CLOCK(5);
GPA_CLOCK(pw[2],0x01);//GPA[0]=pw[2];GPA_CLOCK(1);
GPA_CLOCK(0x00,0x05);//GPA[0]=0x00;GPA_CLOCK(5);
GPA_CLOCK(0x01,0x01);//GPA[0]=0x01;GPA_CLOCK(1);

pw[4]=pw[4]^GPA[0];
GPA_CLOCK(pw[4],0x01);//GPA[0]=pw[4];GPA_CLOCK(1);
GPA_CLOCK(0x00,0x05);//GPA[0]=0x00;GPA_CLOCK(5);

return pw[4];
}*/

//*******************set_user_zone************************
//选择用户区
//zone:用户区序号
//**********************************************************
void set_user_zone(unsigned char zone)
{
unsigned char idata zon[4];

GPA_CLOCK(zone,0x01);
zon[0]=0xb4;
zon[1]=0x03;
zon[2]=zone;
zon[3]=0x00;
write(zon);
Wait_For_AckPolling();
}
//**************************read_user_zone**************************
//读出用户区密文数据,并解出明文数据
//rd_high_addr 用户区高字节地址
//rd_low_addr 用户区低字节地址
//rd_number 读取密文数据及解出明文数据的个数
//解密出的明文数据存放在rwdata[0x04]=>rwdata[0x13]
//******************************************************************
void read_user_zone(unsigned char idata rd_high_addr,unsigned char idata rd_low_addr,unsigned char idata rd_number)
{
unsigned char j;

rwdata[0]=0xb2;
rwdata[1]=rd_high_addr;
rwdata[2]=rd_low_addr;
rwdata[3]=rd_number;
read(rwdata);
Wait_For_AckPolling();

//初始化解密
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(rd_low_addr,0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(rd_number,0x01);

for(j=0;j{
rwdata[4+j]=rwdata[4+j]^GPA[0];
GPA_CLOCK(rwdata[4+j],0x01);
GPA_CLOCK(0x00,0x05);
}
}

//**************************read_config_zone**************************
//读出用户区密文数据,并解出明文数据
//rd_high_addr 用户区高字节地址
//rd_low_addr 用户区低字节地址
//rd_number 读取密文数据及解出明文数据的个数
//解密出的明文数据存放在rwdata[0x04]=>rwdata[0x13]
//******************************************************************
void read_config_zone(unsigned char idata rd_high_addr,unsigned char idata rd_low_addr,unsigned char idata rd_number)
{
unsigned char j;

rwdata[0]=0xb6;
rwdata[1]=rd_high_addr;
rwdata[2]=rd_low_addr;
rwdata[3]=rd_number;
read(rwdata);
Wait_For_AckPolling();

//初始化解密
GPA_CLOCK(0x00,0x05);
GPA_CLO

CK(rd_low_addr,0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(rd_number,0x01);

for(j=0;j{
if(rd_low_addr>=0xb0)
{rwdata[4+j]=rwdata[4+j]^GPA[0];}
GPA_CLOCK(rwdata[4+j],0x01);
GPA_CLOCK(0x00,0x05);
}
}

//*************************encrypto_data*******************************
//对明文数据进行加密
//encryptodatanumber加密数据的个数
//需加密的明文数据存放在 rwdata[4]至rwdata[0x13]
//*********************************************************************
void encrypto_data(unsigned char encryptodatanumber)
{

unsigned char j;
unsigned char temp;
for(j=0;j{
GPA_CLOCK(0x00,0x05);
temp=rwdata[4+j];
rwdata[4+j]=rwdata[4+j]^GPA[0];
GPA_CLOCK(temp,0x01);
}
}

//***************send checksum********************
//功能:发送校验和到器件(以密文形式写入数据后,需发送校验和)
//**************************************************
void send_checksum()
{
unsigned char idata dat6[6];

dat6[0]=0xb4;
dat6[1]=0x02;
dat6[2]=0x00;
dat6[3]=0x02;

GPA_CLOCK(0x00,0x0f);
dat6[4]=GPA[0];
GPA_CLOCK(0x00,0x05);
dat6[5]=GPA[0];

write(dat6);
}
//************************write_user_zone*********************************
//功能:把已加密了的密文数据写到器件
//wr_high_addr 用户区高字节地址
//wr_low_addr 用户区低字节地址
//wr_number 写入数据的个数
//将存放在 rwdata[4]至rwdata[0x13]明文数据写入器件
////////////////////////////////////////////
void write_user_zone(unsigned char wr_high_addr,unsigned char wr_low_addr,unsigned char wr_number)
{
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(wr_low_addr,0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(wr_number,0x01);

rwdata[0]=0xb0;
rwdata[1]=wr_high_addr;
rwdata[2]=wr_low_addr;
rwdata[3]=wr_number;
encrypto_data(wr_number);
write(rwdata);
delay_ms();delay_ms();delay_ms();delay_ms();delay_ms();
send_checksum();
Wait_For_AckPolling();
}

//************************write_user_zone*********************************
//功能:把已加密了的密文数据写到器件
//wr_high_addr 用户区高字节地址
//wr_low_addr 用户区低字节地址
//wr_number 写入数据的个数
//将存放在 rwdata[4]至rwdata[0x13]明文数据写入器件
////////////////////////////////////////////
void write_config_zone(unsigned char wr_high_addr,unsigned char wr_low_addr,unsigned char wr_number)
{
unsigned char j;
unsigned char temp;
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(wr_low_addr,0x01);
GPA_CLOCK(0x00,0x05);
GPA_CLOCK(wr_number,0x01);

rwdata[0]=0xb4;
rwdata[1]=wr_high_addr;
rwdata[2]=wr_low_addr;
rwdata[3]=wr_number;
//encrypto_dat

a(wr_number);
for(j=0;j{
GPA_CLOCK(0x00,0x05);
temp=rwdata[4+j];
if(wr_low_addr>=0xb0)
{rwdata[4+j]=rwdata[4+j]^GPA[0];}
GPA_CLOCK(temp,0x01);
}

write(rwdata);
delay_ms();delay_ms();delay_ms();delay_ms();delay_ms();
send_checksum();
Wait_For_AckPolling();
}


//****************明文读写部分******************************
//****************verify_sc_plaintext****************************
//功能:校验安全密码(传输密码),该密码位置在write7_password
//在器件熔丝未断前,校验安全密码成功后,可以对器件配置区,用户区的随意读写
//sc_firsr_byte 密码的第1个字节数据
//sc_second_byte 密码的第2个字节数据
//sc_third_byte 密码的第3个字节数据
//如verify_sc_plaintext(0xDD,0x42,0x97)
//0xDD,0x42,0x97分别为密码的第123个字节数据
//*****************************************************************
unsigned char verify_sc_plaintext(unsigned char sc_first_byte,unsigned char sc_second_byte,unsigned char sc_third_byte)
{
unsigned char idata scdata[7];
scdata[0]=0xBA;
scdata[1]=0x07;
scdata[2]=0x00;
scdata[3]=0x03;
scdata[4]=sc_first_byte;
scdata[5]=sc_second_byte;
scdata[6]=sc_third_byte;
write(scdata);

scdata[0]=0xb6;///读回PAC_WR7
scdata[1]=0x00;
scdata[2]=0xE8;
scdata[3]=0x01;
read(scdata);
return scdata[4];
}

//************************set_user_zone_plaintext***********************
//选择用户区(明文)
//zonep:用户区序号
//*********************************************************************
void set_user_zone_plaintext(unsigned char zonep)
{
unsigned char idata zon[4];
zon[0]=0xb4;
zon[1]=0x03;
zon[2]=zonep;
zon[3]=0x00;
write(zon);
}

//**************************read_paintext************************************
//读操作(明文)
//rd_cmd:0xb2 读用户区 /0xb6 读配置区 /0xb6 0x01 0x00 0x01 读熔丝
//A1 :高字节地址
//A2 :地字节地址
//N :读取数据个数
//*******************************************************************************
void read_paintext(unsigned char rd_cmd,unsigned char A1,unsigned char A2,unsigned char N)
{
rwdata[0]=rd_cmd;//0xb2 或 0xb6
rwdata[1]=A1; //A1
rwdata[2]=A2; //A2
rwdata[3]=N; //N
read(rwdata);
}

//**************************write_paintext************************************
//写操作(明文)
//rd_cmd:0xb0 写用户区 /0xb4 写配置区 /0xb4 0x01 ID 0x00 写熔丝
//A1 :高字节地址
//A2 :地字节地址
//N :写数据个数
//注意:烧断熔丝时只能从ID=0x06=>0x04=>0x00
//*******************************************************************************
void write_paintext(unsigned char wr

_cmd,unsigned char A1,unsigned char A2,unsigned char N)
{
rwdata[0]=wr_cmd;//0xb0 或 0xb4
rwdata[1]=A1; //A1
rwdata[2]=A2; //A2
rwdata[3]=N; //N
write(rwdata);
}


相关主题
文本预览
相关文档 最新文档