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

📄 ds2401a.c

📁 DS2401增强型硅序列号是一款低成本的电子注册码
💻 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 + -