STC MCU都具有唯一的MCU ID号,一般保存在RAM的0xF1-F7区域,对于15系列,同时会保存在ROM的最后7个字节中。因此,可以通过字符指针,获取MCU ID值,用于程序的加密。
// 读取 STCMCU 的唯一性ID的例程
#define ID_ADDR_RAM
0xF1 //ID号的存放在RAM区的地址为0F1H#define ID_ADDR_ROM
0x0FF9 //4K程序空间的MCU(如STC15F204EA, STC15F104EA)unsigned char UID[
8];
#define RAMID
0#define ROMID
1char *GetMCUID(
unsigned char nType);
//获取 MCU ID.char *GetMCUID(
unsigned char nType)
{
unsigned char idata *iptr;
unsigned char code *cptr;
unsigned char i;
unsigned char bb[
8];
if (nType == RAMID) {
iptr = ID_ADDR_RAM;
//从RAM区读取ID号 for (i=
0; i<
7; i++) {
//读7个字节 UID[i] =*iptr++;
sprintf(bb,
"%02x",(
int)UID[i]);
//***在 Keil C51中,如果想得到正确的2字符十六进制数输出,必须使用(int)形式做转换。 SendStr(bb);
}
}
else {
cptr = ID_ADDR_ROM;
//从程序区读取ID号 for (i=
0; i<
7; i++) {
//读7个字节 UID[i] =*cptr++;
sprintf(bb,
"%02X",(
int)UID[i]);
SendStr(bb);
}
}
UID[7]=
0;
return UID;
}
实际运行的结果如下:

可以看出,RAMID都是0,但是ROM ID 是正确的。
目前的疑问是:RAM无法读取,获得的数据会发生变化。ROM区则读取正确稳定。程序使用 Keil C51 V954a 编译,采用小内存模式。问题原因未找到。
Program Size: data=100.6 xdata=0 code=2397
查看该程序的M51链接内存配置文件,可以看到内存分配如下:
TYPE BASE LENGTH RELOCATION SEGMENT NAME
----------------------------------------------------- * * * * * * * D A T A M E M O R Y * * * * * * *
REG 0000H 0008H ABSOLUTE "REG BANK 0"
0008H 0018H *** GAP ***
BIT 0020H.0 0001H.1 UNIT _BIT_GROUP_
BIT 0021H.1 0000H.5 UNIT ?BI?STCUARTDEMO
0021H.6 0000H.2 *** GAP ***
DATA 0022H 0038H UNIT _DATA_GROUP_
DATA 005AH 0022H UNIT ?DT?STCUARTDEMO
IDATA 007CH 0001H UNIT ?STACK
目前最大的怀疑是Timer0ISR用作模拟串口,在使用时多次中断,导致堆栈增长损坏了idata区域。STC15F204EA的堆栈是向上增长的,以便初始化的栈底值最小,使用PUSH指令增加一些 数据存储时,SP的值会增大。这样可能导致IDATA的数据区0xF1-0xF7(MCUID)区被破坏。但因为无法实际做在线仿真,不能验证此原因。