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

📄 at88scxx.c

📁 Atmel公司推出了最新的加密芯片AT88SC0104C~25616C系列
💻 C
📖 第 1 页 / 共 3 页
字号:
#include<reg52.h>
#include<intrins.h>
#define _Nop()_nop_()            // 延时1us
sbit SDA=P1^3;                   // 定义SDA
sbit SCL=P1^2;                   // 定义SCL
sbit pwr=P3^5;                   // 供电

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

unsigned char 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 IIC_Initial(void);//上电后初始化IIC

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 rd_high_addr,unsigned char rd_low_addr,unsigned char rd_number);
                 //读出用户区密文数据,并解出明文数据
                 //rd_high_addr 用户区高字节地址
                 //rd_low_addr  用户区低字节地址
                 //rd_number    读取密文数据及解出明文数据的个数
                 //解密出的明文数据存放在rwdata[0x04]=>rwdata[0x13]

void read_config_zone(unsigned char rd_high_addr,unsigned char rd_low_addr,unsigned char rd_number);
                 //当rd_low_addr往后不应滚动到0xb0
                 //如想读 0xb0<rd_low_addr<0xef 单元则应重新调用

void encrypto_data(unsigned char encryptodatanumber);
                 //对明文数据进行加密
                 //encryptodatanumber加密数据的个数
                 //需加密的明文数据存放在 rwdata[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<rd_low_addr<0xef 单元则应重新调用
                 //熔丝断后不可写

//****************明文读写部分******************************
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 j;
unsigned char AAC;    //AAC=0xFF则表明校验GCx正确
unsigned char PAC;    //PAC=0xFF则表明校验PWx正确
pwr=0;                      //上电
AAC=0;
PAC=0;
IIC_Initial();
//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=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 j;
     for(j=0x00;j<255;j++)
        {
          _Nop();_Nop();_Nop();
        }
}

//***********************IIC_Initial***********************************
//功能:上电后初始化IIC
//*****************************************************************
void IIC_Initial(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
}

//***********************SMSTART***********************************
//功能:启动I2C
//*****************************************************************
void SMSTART(void)
{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 din_gpa;
unsigned char Ri;
unsigned char R_Sum;
unsigned char Si;
unsigned char S_Sum;
unsigned char Ti;
unsigned char T_Sum;

 for(t=0x00;t<times;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));}

⌨️ 快捷键说明

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