📄 ds2401a.c
字号:
#include "Global.h"
BYTE cMachineType; //
DWORD dwTimeLimit; //
BYTE cLimitTime[10]; //
BYTE CheckResult; //
void Delayus( WORD wTimeLong )
{
WORD i,j;
for( i=0; i<wTimeLong; i++ )
for( j=0; j<10; j++ );
}//Delayus
//*******************ReadOneBit**************************
//从2401读1bit,2401的数据在通信线的上升沿输出
BYTE ReadOneBit(void)
{
BYTE bResult;
OutputEN();//输出使能
Delayus(1);
//产生上升沿
Clr2401();
Delayus(5);
Set2401();
InputEN();//读使能
Delayus(10);
bResult = Read2401();
Delayus(50);
return( bResult );
}//ReadOneBit
//*******************ReadOneBit**************************
//*******************ReadSN2401**************************
//从2401读出串行码:先发复位信号,再发写命令0x33,然后读,在整个过程关闭中断
void ReadSN2401( BYTE *cpDst )
{
WORD i,j,bOptBit;
DisableInt();
OutputEN();//输出使能
Delayus(1);
//发复位信号
Clr2401();
Delayus(500);
Set2401();
InputEN();//读使能,放弃总线占有权
//这一句必须有,否则读不到结果
Delayus(450);
//发写命令0x33
OutputEN();//输出使能
i = 0x33;
bOptBit = 1;
for( j=0; j<8; j++ )
{
if( i & bOptBit )
{
Clr2401();
Delayus(8);
Set2401();
Delayus(70);
}
else
{
Clr2401();
Delayus(65);
Set2401();
Delayus(12);
}
bOptBit <<= 1;
}
for( i=0; i<8; i++ ) //共8个字节
{
bOptBit = 1;
for( j=0; j<8; j++ ) //读1个字节
{
if( ReadOneBit() )
*(cpDst+i) |= bOptBit;
else
*(cpDst+i) &= ~bOptBit;
bOptBit <<= 1;
}
}
OutputEN();//输出使能
Set2401(); //读完之后把通信线拉高
EnableInt();
}//ReadSN2401
//*******************ReadSN2401**************************
//*******************WriteSN2401**************************
//SN2401的数据存放在0x00007100开始的地址空间上
BYTE WriteSN2401(void)
{
DWORD *add;
DWORD data32[3];
BYTE data8[8];//存放从DS2401读出的8字节数据
//rWDMOD = 0;//禁止WDT
//先把状态读出来
add = (DWORD *)0x00007000;
data32[0] = *add;
//读DS2401
ReadSN2401(data8);
//CRC校验读出的数据
if(CheckDS2401CRC(data8)==FALSE)
return CRC_ERROR;//不正确则退出函数
else
{
//加密2401数据
EncryptSN(data8);
//把数据转存进双字变量
data32[1] = 0;
data32[2] = 0;
data32[1] = ((DWORD)data8[3]<<24) | ((DWORD)data8[2]<<16) | ((DWORD)data8[1]<<8) | data8[0];
data32[2] = ((DWORD)data8[7]<<24) | ((DWORD)data8[6]<<16) | ((DWORD)data8[5]<<8) | data8[4];
//向FLASH写入数据(状态字和2401处理后的数据)
DisableInt();
SelSector(7,7);
EraseSector(7,7);
SelSector(7,7);
RamToFlash(0x00007000, (DWORD)data32, 256);
EnableInt();
return TRUE;
}
//InitWDT();//启动WDT
}//void WriteSN2401(void)
//*******************WriteSN2401**************************
//*******************CRC**************************
//CRC校验,最后的结果在B中
void CRC( BYTE A, BYTE *B )
{
BYTE C,i,tempA = A;
for( i=0; i<8; i++ )
{
A ^= *B;
C = A & 0x01;
A = *B;
if( C ==1 )
A ^= 0x18;
A /= 2;
A += (C<<7);
*B = A;
tempA /= 2;
A = tempA;
}
}//CRC
//*******************CRC**************************
//*******************CheckDS2401CRC*********************
//校验读到的串行码是否正确
//从2401读到的串行码第一字节是厂商码,所有2401都相同
//然后是6字节的串行码,最后一个是CRC校验码
//前面7个字节做CRC校验之后应该等于第8个字节
BYTE CheckDS2401CRC( BYTE *cpSrc )
{
BYTE i,B=0;
for( i=0; i<7; i++ )
CRC( *(cpSrc+i) , &B );
if( *(cpSrc+7) == B )
return TRUE;
else
return FALSE;
}//CheckDS2401CRC
//*******************CheckDS2401CRC*********************
//*******************MUL*********************
//6字节×6字节,按字符串的形式相乘
void MUL( BYTE *cpSrc )
{
BYTE i,j;
DWORD Mul[] = { 0xA7, 0x5B, 0xC9, 0x26, 0x0D, 0xA5 };
DWORD c,Temp,Result[12];
//结果缓冲区清零
for( i=0; i<12; i++ )
Result[i] = 0;
for( j=0; j<6; j++ ) //考察乘数的每一个字节
{
c=0; //进位清零
for( i=0; i<6; i++ ) //对于乘数的每一个字节,都扫描一遍被乘数
{
Temp = *(cpSrc+i) * Mul[j] + c; //乘数和被乘数各自一个字节相乘,再加上进位
Result[i+j] += (Temp % 256); //上面的结果MOD256,再加进结果的相应字节
c = Temp / 256; //求进位
}
}
//对结果进行调整,只取8个字节,故多出的字节没必要调整
for( i=0; i<8; i++ )
{
*(cpSrc+i) = Result[i] % 256;
c = Result[i] / 256;
Result[i+1] += c;
}
}//MUL
//*******************MUL*********************
//*******************Exchange****************
//把字节顺序倒乱
void Exchange( BYTE *pcSrc )
{
BYTE i,cTemp[8];
cTemp[0] = *(pcSrc+3);
cTemp[1] = *(pcSrc+5);
cTemp[2] = *(pcSrc+0);
cTemp[3] = *(pcSrc+7);
cTemp[4] = *(pcSrc+2);
cTemp[5] = *(pcSrc+6);
cTemp[6] = *(pcSrc+1);
cTemp[7] = *(pcSrc+4);
for( i=0; i<8; i++ )
*(pcSrc+i) = cTemp[i];
}//Exchange
//*******************Exchange****************
//*******************RLC*********************
//把输入的字节 cSrc 左循环移 cBits 位
BYTE RLC( BYTE cSrc , BYTE cBits )
{
WORD wTemp;
BYTE i,cTemp;
wTemp = cSrc;
for( i=0; i<cBits; i++ )
wTemp *=2;
cTemp = (wTemp>>8)&0x00FF;
wTemp += cTemp;
wTemp &= 0x00FF;
return( (BYTE)wTemp );
}//RLC
//*******************RLC*********************
//*******************RRC*********************
//把输入的字节 cSrc 右循环移 cBits 位
BYTE RRC( BYTE cSrc , BYTE cBits )
{
WORD wTemp;
BYTE i,cTemp;
wTemp = cSrc<<8;
for( i=0; i<cBits; i++ )
wTemp /=2;
cTemp = (wTemp>>8)&0x00FF;
wTemp += cTemp;
wTemp &= 0x00FF;
return( (BYTE)wTemp );
}//RRC
//*******************RRC*********************
//*******************EncryptSN*********************
//对读到的2401SN码进行加密
void EncryptSN( BYTE *cpSrc )
{
BYTE i;
//只取SN码中间6个字节
for( i=0; i<6; i++ )
*(cpSrc+i) = *(cpSrc+i+1);
//其它字节清零
for( i=6; i<8; i++ )
*(cpSrc+i) = 0;
//乘上一个6字节的常数
MUL( cpSrc );
//倒乱结果的字节位置
Exchange( cpSrc );
//对不同的字节分别进行不同的循环左移或者循环右移
for( i=0; i<8; i++ )
if( i%2 == 0 )
{
*(cpSrc+i) = RLC( *(cpSrc+i), ((i/2+6)%4)+1 ); //偶字节进行不同的循环左移
*(cpSrc+i) ^= 0xB4; //结果再异或 0xB4
}
else
{
*(cpSrc+i) = RRC( *(cpSrc+i), (i%3)+1 ); //奇字节进行不同的循环右移
*(cpSrc+i) ^= 0x69; //结果再异或 0x69
}
//对第四个字节进行特殊处理
for( i=0; i<8; i++ )
*(cpSrc+3) += *(cpSrc+i);
*(cpSrc+3) %= 256;
//对第六个字节进行特殊处理
for( i=2; i<7; i++ )
*(cpSrc+5) += *(cpSrc+i);
*(cpSrc+5) %= 256;
}//EncryptSN
//*******************EncryptSN*********************
//*******************CheckSN*********************
//判断从2401读出并加密后的SN码跟从FLASH中读出的SN码是否一致
BYTE CheckSN(void)
{
BYTE data8[8];
DWORD data32[2];
DWORD *add;
DWORD temp0,temp1;
//先读出DS2401的数据并处理好
//读DS2401
ReadSN2401(data8);
//CRC校验读出的数据
if(!CheckDS2401CRC(data8))
return CRC_ERROR;//不正确则退出函数
else
{
//加密2401数据
EncryptSN(data8);
//把数据转存进双字变量
data32[0] = 0;
data32[1] = 0;
data32[0] = ((DWORD)data8[3]<<24) | ((DWORD)data8[2]<<16) | ((DWORD)data8[1]<<8) | data8[0];
data32[1] = ((DWORD)data8[7]<<24) | ((DWORD)data8[6]<<16) | ((DWORD)data8[5]<<8) | data8[4];
//读出FLASH中的DS2401数据
add = (DWORD *)0x00007004;
temp0 = *add;
add = (DWORD *)0x00007008;
temp1 = *add;
//比较
if((temp0==data32[0])&&(temp1==data32[1]))
return( SN_OK );
else
return( SN_ERROR );
}
}//CheckSN
//*******************CheckSN*********************
//*******************Noise2401*********************
//平时不读取2401时不断向它发干扰脉冲
void Noise2401( void )
{
BYTE i,j,bOptBit;
BYTE cTime; //脉冲波之间的随机延时时间
BYTE cWave; //随机产生的脉冲波形
cWave = ((DWORD)LedTimeCount*19)%251 + 3; //产生随机脉冲波形
bOptBit = 1;
for( i=0; i<8; i++ )
{
if( cWave & bOptBit ) //输出cWave中相应于bOptBit的位
Set2401();
else
Clr2401();
cTime = ((DWORD)LedTimeCount*13)%191 + 57; //产生随机的延时时间
for( j=0; j<cTime; j++ ); //延时
bOptBit <<= 1; //移向下一位
}
Set2401(); //最后都对2401保持高电平,避免2401不必要的复位
}//Noise2401
//*******************Noise2401*********************
//密码错误执行的程序
void WrongPassword(void)
{
DWORD i;
ColorSelect = 2;
AllOn();
for(i=0;i<1500000;i++);
ClrDisplay();
for(i=0;i<1500000;i++);
}//void WrongPassword(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -