编程器的介绍可查看:http://www.qcfdlt.com
TL866编程器有个自动编号功能,可利用DLL动态库调用实现任意的序列号.如何使用DLL设定序列
号,可参考编程器安装包内的DLL实例,内有详细说明。后面讲的用单片机唯一的特性标识进行加密也
用到DLL调用,基本大同小异。
经过这样的加密,达到一个目的,就是解密者必须修改你的软件后才能放心使用,但是每次升级同
样会受你控制,好像微软随时可以黑你屏一样的道理,否则可能随时会被你宰了!!但这种方法只适合
连接PC或网络的系统。
三、用单片机唯一的特征标识进行加密
加密原理:
单片机必须有唯一标志,单片机程序内只要判断是否是这个标志,就可防止程序直接复制使
用。理论上可以做到很难**,本人认为是最有效又实用的方法。
达到目的: 解密者最不愿意做的事让他必须做。
一般大部分搞单片机解密的都是暴力**,因为这个最容易,只要牚握技巧,有设备,工艺熟练就可了,不用太强的专业知识。如果复制后,程序无法运行,那就蒙了,因为这个时候就要去看汇编语言了,我想信有很多汇编高手,能很容易**。但我也同时认为,怎么多型号的单片机,汇编指令差别好大,每一种单片机的汇编都很熟的人应不多了。所以这会大大增加**难度。如果一个加密设计好的软件,跟据单片机的唯一特征字来加密,有时他可能不得不看懂里面的加密算法。这样加密目的就达到了。
开发人员需要做的事:
有了唯一特征字,并不是加密万无一失了。如果你只是在程序中只用一条语句判断,是不是这个芯片的特征字,则程序被读出后,解密者只要简单的修改程序,直接跳过判断语句。可能只要几分钟就解决了。所以在程序要加入加密算法,尽量不用IF判断语句。可用子程序调用地址来参与特征字的加密运算等等方法,如何防反汇编及修改软件等不在这里讨论,网上可以找到有关这方面的很多资料。
下面讨论如何用TL866编程器实现,单片机用特征字进行加密的量产操作:
芯片进行加密量产操作同样碰到到一个问题,如果加密算法比较复杂,每个芯片在代码中需要更改的数据较多,用手工的方法是无法实现量产操作编程的,TL866编程器很好的解决了这个问题,下面用ATMEGA8为例,说明TL866编程器如果进行加密量产编程操作。TL866编程器程序安装包(V3.01以上)中有该实例的全部动态库函数及单片机C源代码,稍作修改就可用到你的产品中。
下载地址:http://www.qcfdlt.cn//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ATMEGA8加密编程实例
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1、ATMEGA8 实例原理图
2、加密测试方法
测试步骤:
1. 选择ATMEAG8芯片
2. 调入OBJ录中的HEX数据文件到缓存CODE区
配置信息设定,默认不更改。
3. 设定DLL加密算法
这个过程同自定义编号算法
方法:<主菜单>--<操作>--<自动编号设定>
在对话框内设定自定义算法Get_M8_LED_DATA.dll,并选中允许自动编号后保存
4.在主程序左下角选择<允许自动编号>,编程芯片。
(配置位选择不进行物理加密,否则后面读不出这个芯片的内容进行复制)
5.按原理图连接电路,通电测试,LED有规律闪动正常。
6.读取刚编程芯片内的程序,把这个程序复制到另一个芯片中,运行测试结果。
(复制芯片时,不可调用DLL算法,否则芯片中是按这个芯片RC值得出的数据)
此时LED,无规律闪动。测试完成。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ICCAVR C源程序说明
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本程序在ATMEGA8上 用ICCAVR 6.31A测试通过
***************************************************************
程序功能:
正常情问况下,程序按数组表是的顺序点亮LED,LED有规律地循环闪动。当程序从正常芯片中被复制到另一个ATMEGA8芯片上时你可看到程序工作异常,LED闪动混乱。
目的:本程序只是演示,如何使用TL866编程器对AVR单片机量产加密.原理是各芯片的RC校正字节不同,进行软件加密。使即使芯片被**,它的程序被读出, 也无法直接使用 .本加密只是用了一个数组异或,你可用任何你能想到的方法进行加密,并可在原代码中加入程序CRC校验,防止原代码修改等等方法。
单片机溶丝位设定: 默认
**************************************************************/
/*定义LED按一定正常顺序显示的数组
1. table1 table2这两个数组定位到固定的地址, 是为了编程器可以保证访问到这些数据位置在没有加密的情况下,table1这个数组是一个亮灯的明码,这种情况下程序复制到任何一个芯片上都可正常运行,这里演示的加密主要是准对这个数组进行算法变换
2. table2是一个任意值的数组,
*/
#pragma abs_address:0x800
//正常的亮灯顺序,//在具体加密中你可把它当成--子程序入口表
编程器编时里会自动放入反向的加密数据
const char table1[] =
{
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
};
定义一个这个表是为了给数组绝对定位的空间,这个表中的值无意义
const char table2[] =
{
0xA5, 0x00, 0xE6, 0xBF, 0x46, 0x70, 0xE3, 0x2A, 0x22, 0xBE, 0x90, 0x9C, 0xA1, 0x05, 0xAE, 0xA5,
0xA0, 0xFE, 0x24, 0x5D, 0x66, 0x22, 0x97, 0xA7, 0xD9, 0x0F, 0x3C, 0xB7, 0xF1, 0x2D, 0xEA, 0xD2,
0x6E, 0x91, 0x74, 0x55, 0xC6, 0x22, 0x35, 0xF9, 0x62, 0xFA, 0xEC, 0x55, 0x09, 0x0F, 0xCB, 0xA5,
0x9D, 0x12, 0xCA, 0xC9, 0x05, 0x97, 0x41, 0x91, 0x6A, 0x77, 0xB6, 0x37, 0xA6, 0x72, 0xF3, 0x2D,
0xF9, 0x19, 0x5C, 0x19, 0xFE, 0xEC, 0x80, 0x1F, 0xDE, 0xBF, 0xEE, 0x5E, 0xC4, 0x62, 0x4A, 0xBD,
0x91, 0x80, 0xA0, 0xE7, 0xD0, 0xC8, 0xF7, 0x94, 0xEC, 0x4B, 0x2A, 0x0B, 0xA0, 0x25, 0xF3, 0xE4,
0xB0, 0x60, 0x49, 0x13, 0xD7, 0x15, 0xEC, 0x22, 0x00, 0xD4, 0x3E, 0xBE, 0xB9, 0x46, 0x54, 0x75,
0xE4, 0x11, 0x4D, 0xBE, 0xAF, 0xFC, 0xE2, 0x3A, 0xC7, 0x54, 0x3F, 0x39, 0xC9, 0x8E, 0x11, 0x80,
0xFA, 0x2D, 0xE1, 0x4A, 0x37, 0xE7, 0xA0, 0x8C, 0x2F, 0x03, 0x83, 0x7D, 0xCF, 0x05, 0x11, 0x56,
0xFE, 0x8D, 0x7A, 0x56, 0x8B, 0x7D, 0x2A, 0x0A, 0x63, 0x5A, 0x9E, 0xCB, 0x08, 0xF5, 0x76, 0x88,
0x3E, 0x4A, 0xCC, 0xC6, 0x08, 0xA8, 0xC5, 0xE4, 0xD2, 0x12, 0x65, 0xA4, 0xF0, 0xE6, 0xA8, 0xE7,
0x47, 0xBC, 0xCE, 0xB8, 0x4A, 0x91, 0xF6, 0x8C, 0x29, 0x25, 0xEE, 0xC8, 0x44, 0xA1, 0x4A, 0x84,
0xE6, 0x7D, 0xB3, 0x8F, 0x30, 0xA1, 0x82, 0xB3, 0x53, 0xCA, 0x8E, 0x3A, 0x03, 0x30, 0x41, 0xB0,
0x28, 0x66, 0xF2, 0xEB, 0xD6, 0x81, 0x6E, 0x49, 0x7F, 0x7C, 0xD8, 0x39, 0x67, 0xDB, 0xB4, 0xFD,
0x59, 0x8F, 0x3E, 0xAE, 0x99, 0x1A, 0x00, 0x80, 0x19, 0xF3, 0xA3, 0x47, 0xEF, 0x2C, 0x06, 0x3A,
0x07, 0x52, 0x8D, 0xF7, 0x15, 0x95, 0xBC, 0xC8, 0xCE, 0x28, 0x04, 0x25, 0x58, 0xEB, 0xDC, 0x7A
};
#pragma end_abs_address
/*延时程序*/
void Delay(void)
{
unsigned int i;
for(i=0;i<0x1000;i++);
}
/********************************************************************************
* Main 主程序
* 从是可以看出,本程序中没有IF语句,解密只能修改OSCCAL的值或修改数据表
* 如果你在程序中,加入程序代码校验,则必须先取消校验,才能**。相信你可加入更多的
* 方法来防止解密者修改源程序
*********************************************************************************/
void main()
{
unsigned char i,TempChar;
/*PORTB接LED灯*/
DDRB = 0xFF; /* PORTB引脚全为输出*/
PORTB = 0x00; /* 输出低电平 */
i=0;
while(1)
{
//----------------------------------------------------------
/*TempChar=table1;/*不加密时的输出方法*/
//------------------------------------------------------------------
/*加密时的输出方法*/
//-------------------------------------------------------------------
/*异或的开始位置与OSCCAL有关,这样OSCCAL变动数据会全乱*/
TempChar=table2[(i+OSCCAL)&0xFF]^table1;
TempChar^=OSCCAL;
/*这时的输出是OSCCAL寄存器与数据表中的值异或后的结果
默认情况OSCCAL的值就是ATMEGA8,默认1M的校正字节*/
/*这样二步运算结果,当然必须要做到,PORTB最后的结果和明码状态一样
也就是说,OSCCAL参与运算后的结果必须最后得出明码值,这样LED才正常.
这就要求编程器能在编程根据芯片的RC校正值自动生成table1[]及table2[]
表,使得最后运行的结果为正确的明码,*/
/*可以想像,因为OSCCAL值每个芯片不同,table1[]及table2[]表的数据放到
另一个芯片里面。最后运行的结果一定的错误的,达到加密的目的*/
//------------------------------------------------------------------------------
i++;
PORTB=TempChar;/*输出*/
Delay();
}
}
/*下一步我们来看看TL866编程器在编程芯片时需要做的:
第1步:读取RC校正字节值
第2步:随机生成一个table2的数据表,这是为迷惑**者的,table2每个芯片不同。
第3步: 根据RC值,Tables2表,明码表,---->反向计算出Table1表的数据
使单片机运算时能根据RC、Table1、Tables2表的数据刚好得到明码表。
第4步:将计算出的table1[],和前面随机生成的table2[]放入缓存写入到芯片中。
具体可查看安装目录内对应DLL原代码
通过以上工作后,即使芯片内程序被读出,放入到另一个芯片中程序也无法正常工作。
这里只是通过一个简单的示例,说明TL866编程器如何与单片机软件配合起来,进行
产品的量产过程。
实际使用的加密,应加入更多的加密算法,反跟踪,及原代码校验防止程序修改等等,
使**者必须认真看懂你的原代码,才能进行程序修改**。
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DLL动态库函数说明
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//定义一个正常的LED亮灯顺序表
//在具体加密中你可把把它放子程序入口表
const unsigned char table1[] =
{
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /*1个灯亮走动*/
};
//定义一个随机表,这个表每个芯片不同随机生成
unsigned char table2[] =
{
0xA5, 0x00, 0xE6, 0xBF, 0x46, 0x70, 0xE3, 0x2A, 0x22, 0xBE, 0x90, 0x9C, 0xA1, 0x05, 0xAE, 0xA5,
0xA0, 0xFE, 0x24, 0x5D, 0x66, 0x22, 0x97, 0xA7, 0xD9, 0x0F, 0x3C, 0xB7, 0xF1, 0x2D, 0xEA, 0xD2,
0x6E, 0x91, 0x74, 0x55, 0xC6, 0x22, 0x35, 0xF9, 0x62, 0xFA, 0xEC, 0x55, 0x09, 0x0F, 0xCB, 0xA5,
0x9D, 0x12, 0xCA, 0xC9, 0x05, 0x97, 0x41, 0x91, 0x6A, 0x77, 0xB6, 0x37, 0xA6, 0x72, 0xF3, 0x2D,
0xF9, 0x19, 0x5C, 0x19, 0xFE, 0xEC, 0x80, 0x1F, 0xDE, 0xBF, 0xEE, 0x5E, 0xC4, 0x62, 0x4A, 0xBD,
0x91, 0x80, 0xA0, 0xE7, 0xD0, 0xC8, 0xF7, 0x94, 0xEC, 0x4B, 0x2A, 0x0B, 0xA0, 0x25, 0xF3, 0xE4,
0xB0, 0x60, 0x49, 0x13, 0xD7, 0x15, 0xEC, 0x22, 0x00, 0xD4, 0x3E, 0xBE, 0xB9, 0x46, 0x54, 0x75,
0xE4, 0x11, 0x4D, 0xBE, 0xAF, 0xFC, 0xE2, 0x3A, 0xC7, 0x54, 0x3F, 0x39, 0xC9, 0x8E, 0x11, 0x80,
0xFA, 0x2D, 0xE1, 0x4A, 0x37, 0xE7, 0xA0, 0x8C, 0x2F, 0x03, 0x83, 0x7D, 0xCF, 0x05, 0x11, 0x56,
0xFE, 0x8D, 0x7A, 0x56, 0x8B, 0x7D, 0x2A, 0x0A, 0x63, 0x5A, 0x9E, 0xCB, 0x08, 0xF5, 0x76, 0x88,
0x3E, 0x4A, 0xCC, 0xC6, 0x08, 0xA8, 0xC5, 0xE4, 0xD2, 0x12, 0x65, 0xA4, 0xF0, 0xE6, 0xA8, 0xE7,
0x47, 0xBC, 0xCE, 0xB8, 0x4A, 0x91, 0xF6, 0x8C, 0x29, 0x25, 0xEE, 0xC8, 0x44, 0xA1, 0x4A, 0x84,
0xE6, 0x7D, 0xB3, 0x8F, 0x30, 0xA1, 0x82, 0xB3, 0x53, 0xCA, 0x8E, 0x3A, 0x03, 0x30, 0x41, 0xB0,
0x28, 0x66, 0xF2, 0xEB, 0xD6, 0x81, 0x6E, 0x49, 0x7F, 0x7C, 0xD8, 0x39, 0x67, 0xDB, 0xB4, 0xFD,
0x59, 0x8F, 0x3E, 0xAE, 0x99, 0x1A, 0x00, 0x80, 0x19, 0xF3, 0xA3, 0x47, 0xEF, 0x2C, 0x06, 0x3A,
0x07, 0x52, 0x8D, 0xF7, 0x15, 0x95, 0xBC, 0xC8, 0xCE, 0x28, 0x04, 0x25, 0x58, 0xEB, 0xDC, 0x7A
};
/////////////////////////////////////////////////////////////////////////
// 自定义动态函数,函数名称不可更改
// 我们都是利用这个函数,对缓冲区进行编程前的操作,这个函数传递了所有芯片缓冲区的操作地址
// 你可以任意修改缓冲区的内容,你只要进行反向的加密算法,放入数据就可了
// 返回值: 返回对芯片缓冲区操作的区块结果的结构指针PSTRUCOPERATOR
// 参数: 6个缓冲区指针 (应用程序传给DLL的)
// pCode: 对应编程器程序区的数据指针
// pEEdata: 对应编程器数据区的数据指针
// pUserRow: 对应编程器USER ROW的数据指针,
// 在87C51编程时为Envrypt Table加密阵列的指针
// pID: 对应编程器ID区的数据指针
// pSerial: 前一次编程时的序列号
// pSerial 对应值必须为ASCII码字符串(最大长度不可超过32个字符)
// 这个值可以作为一个初始值使用,也可以不使用这个值,如果不使用,需要处理在DLL文件中保存并处理初始编号。
// 使用这个字符串,需要把新的初值放在这个缓冲内,写芯片时,应用程序会自动保存,
// 在编程下一个芯片时,新的值会传送到DLL,这样可省略在DLL文件的初值保存部分程序
// 你也可以把它看成这是个编程器主程序调用DLL的计数据使用
// pUniqueKey: 厂家设定的芯片唯一设别标志指针。对厂家每个芯片设有唯一序列号的单片机(并且无法更改的芯片),可用于自定义
// 加密算法,在程序中对该标志进行加密判断,使芯片中的原代码即使被克隆,也无法在另一个芯片上直接使用。
// 注:对于ATMEL AVR芯片虽没有唯一标识,但本编程器可自动读入RC校正字节,该字节不可更改,几十个芯片才有一个可能相同
// 用户可更改对应存储位置加密算法的数据,使程序只能在这个芯片上正常工作,就可实现对芯片进行加密
// (上电后,单片机软件读入OSCCAL寄存器,就是对应校正字节值)
// 有此方法,可方便实现量产,也可用于自动调入非默认的校正字节到程序中,
// 否则你需要对每个芯片的程序进行分别编译。
//////////////////////////////////////////////////////////////////////
GETSERIAL_API pSTRUCOPERATOR GetSerial(unsigned char * pCode,unsigned char * pEEdata,unsigned char * pUserRow,unsigned char *
pID,char * pSerial,unsigned char * pUniqueKey)
{
//你可在这里读取或改变缓冲区全部数据
//操作注意事项:
//1、对缓冲区的操作,包刮读取或更改内容不可大于当前芯片的容量大小
// 否则可能产生不可预料的严重重错误。
//2、可以6个任意的缓冲区内放入任何数据,例如放入加密算法后的数据
//3、对没有EEDATA 或USER ROW 或ID存储区的芯片,不可操作对应区块的缓存
//4、在允许自动编号的情况下,编程器每测试或编程前,调用一次这个函数。
int i;
unsigned char TempChar;
//随机重新生成一个table2表
srand( (unsigned)time( NULL ) ); //seed
for(i=0x0;i<256;i++)table2=(unsigned char)(rand()&0xFF);
//反向计算table1表,放入0x800处,0x800为单片机中table1表的位置
//这个过程必须与单片机的算法反向,单片机工作时,才能得到正确的值
for(i=0;i<256;i++)
{
//首先RC校正字节与table1明码表异或
TempChar=table1^pUniqueKey[0];
//结果与table[2]表异或,第一个开始位置在OSCCAL处
TempChar^=table2[(i+pUniqueKey[0])&0xFF];
//放入单片机中table1表的位置
pCode[i+0x800]=(unsigned char)TempChar;
}
//放入talbe2表到单片机0x900位置
for(i=0;i<256;i++)
{
pCode[i+0x900]=table2;
}
//////////////////////////////////////////////////////////////////////
//设置操作区块,提示对那些存储区块进行了编号操作
//如果测试时不需要界面显示,OprateResult.nCount=0; 后面的可不设定
OprateResult.nCount=2; //修改了2处
OprateResult.MemoryType[0] = CODE_MEMORY; //第1处的缓冲区类型
OprateResult.StartAddr[0] = 0x800; //第1处的开始地址
OprateResult.Len[0] = 256; //第1处的长度
OprateResult.MemoryType[1] = CODE_MEMORY; //第2处的缓冲区类型
OprateResult.StartAddr[1] = 0x900; //第2处的开始地址
OprateResult.Len[1] = 256; //第2处的长度
return &OprateResult; //返回操作结果
}
结束语:上面的源程序在TLL866编程器安装包内,方法不知是否合理,供大家参考
欢迎光临 陶邦汽车防盗论坛 (http://bbs.qcfdlt.com/) | Powered by Discuz! X3.1 |