当前位置: 首页 > news >正文

STC15读取内部ID示例程序

STC15读取内部ID示例程序


  • 🎉本案例基于STC15F2K60S2为验证对象。

📑STC15 ID序列介绍

  • STC15系列STC最新一代STC15系列单片机出厂时都具有全球唯一身份证号码(ID号)。最新STC15系列单片机的程序存储器的最后7个字节单元的值是全球唯一ID号,用户不可修改,但IAP15系列单片机的 整个程序区是开放的,可以修改,建议利用全球唯一ID号加密时,使用STC15系列单片机,并将EEPROM功能使用上,从EEPROM起始地址0000H开始使用,可以有效杜绝对全球唯一ID号的攻击。
  • 除程序存储器的最后7个字节单元的内容是全球唯一ID号外,单片机内部RAM的F1H ~ F7H单元 (对于STC15F100W系列及STC15W104SW系列单片机是内部RAM的71H - 77H单元)的内容也为全球唯一ID号。用户可以在单片机上电后读取内部RAM单元F1H - F7H (对于STC15F100W系列及STC15W104SW系列单片机是内部RAM单元71H - 77H)连续7个单元的值来获取此单片机的唯一身份证号码(ID号 ), 使用“ MOV @Ri” 指令来读取。如果用户需要用全球唯一ID号进行用户自己的软件加密,建议用户在程序的多个地方有技巧地判断自己的用户程序有无被非法修改,提高解密的难度,防止解密者修改程序,绕过对全球唯一ID号的判断。
  • 使用程序区的最后7个字节的全球唯一ID号比使用内部RAM单元 F1H - F7H (或内部RAM单元71H - 77H)的全球唯一ID号更难被攻击。建议用户使用程序区最后7个字节的全球唯一ID号,而不要使用内部RAM单元 F1H - F7H (或内部RAM单元71H - 77H)的全球唯一ID号。

🌼有关ID号在大批量生产中的应用方法

  1. 先烧一个程序进去(选择下次下载用户程序时,不擦除用户EEPROM区);
    在这里插入图片描述
  2. 读程序区的ID号(STC15系列是程序区的最后7个字节),经用户自己的复杂的加密算法对程序区的ID号加密运算后生成一个新的数——用户自加密ID号,写入STC15系列用户EEPROM区的EEPROM。
  3. 再烧一个最终出厂的程序进去(选择下次下载用户程序时将用户EEPROM区一并擦除),如下图所示:
    在这里插入图片描述
  4. 在用户程序区的多处读程序区的ID号和用户自加密ID号比较(经用户自己的复杂的解密算法解密后),如不对应,则6个月后随机异常,或200次开机后随机异常最终出厂的程序不含加密算法。
  5. 另外,在程序区的多个地方判断用户自己的程序是否被修改,如被修改,则6个月后随机异常,或200次开机后随机异常,将不用的用户程序区用所谓的有效程序全部填满。

📝示例程序

  • ✨以STC15F2K60S2为例,主时钟频率:22.1184MHz,波特率:115200
    在这里插入图片描述
//#include "reg51.h"
#include <STC15F2K60S2.H>
//#include "STC15Fxxxx.H"
//typedef unsigned char u8;
//typedef unsigned    int u16;#define FOSC 22118400L          //系统频率
#define BAUD 115200             //串口波特率#define S1_S0 0x40              //P_SW1.6
#define S1_S1 0x80              //P_SW1.7
bit busy;
//sfr T2H = 0xd6; //定时器2高8位
//sfr T2L = 0xd7; //定时器2低8位
//sfr AUXR = 0x8e; //辅助寄存器
#define ID_ADDR_RAM 0xf1 //ID号的存放在RAM区的地址为0F1H
//ID号的存放在程序区的地址为程序空间的最后7字节
//#define ID_ADDR_ROM 0x03f9 //1K程序空间的MCU(如STC15F201EA, STC15F101EA)
//#define ID_ADDR_ROM 0x07f9 //2K程序空间的MCU(如STC15F402AD,
//STC15F202EA, STC15F102EA)
//#define ID_ADDR_ROM 0x0bf9 //3K程序空间的MCU(如STC15F203EA, STC15F103EA)
//#define ID_ADDR_ROM 0x0ff9 //4K程序空间的MCU(如STC15F404AD, STC15F204EA,
//STC15F104EA)
//#define ID_ADDR_ROM 0x13f9 //5K程序空间的MCU(如 STC15F206EA, STC15F106EA)
//#define ID_ADDR_ROM 0x1ff9 //8K程序空间的MCU(如STC15F2K08S2, STC15F1K08AD,
//STC15F408AD)
//#define ID_ADDR_ROM 0x27f9 //10K程序空间的MCU(如STC15F410AD)
//#define ID_ADDR_ROM 0x2ff9 //12K程序空间的MCU(如STC15F408AD)
//#define ID_ADDR_ROM 0x3ff9 //16K程序空间的MCU(如STC15F2K16S2,
//STC15F1K16AD)
//#define ID_ADDR_ROM 0x4ff9 //20K程序空间的MCU(如STC15F2K20S2)
//#define ID_ADDR_ROM 0x5ff9 //24K程序空间的MCU
//#define ID_ADDR_ROM 0x6ff9 //28K程序空间的MCU
//#define ID_ADDR_ROM 0x7ff9 //32K程序空间的MCU(如STC15F2K32S2)
//#define ID_ADDR_ROM 0x9ff9 //40K程序空间的MCU(如STC15F2K40S2)
//#define ID_ADDR_ROM 0xbff9 //48K程序空间的MCU(如STC15F2K48S2)
//#define ID_ADDR_ROM 0xcff9 //52K程序空间的MCU(如STC15F2K52S2)
//#define ID_ADDR_ROM 0xdff9 //56K程序空间的MCU(如STC15F2K56S2)
#define ID_ADDR_ROM 0xeff9 //60K程序空间的MCU(如STC15W4K60S4,STC15F2K60S2)//-----------------------------------------
void InitUart();
void SendUart(u8 dat);
//-----------------------------------------
void main()
{u8   idata *iptr;u8 code *cptr;u8   i;P0M0 = 0x00;P0M1 = 0x00;P1M0 = 0x00;P1M1 = 0x00;P2M0 = 0x00;P2M1 = 0x00;P3M0 = 0x00;ACC = P_SW1;ACC &= ~(S1_S0 | S1_S1);    //S1_S0=0 S1_S1=0
//	S1_USE_P30P31();        //UART1 使用P30 P31口   默认InitUart(); //串口初始化iptr = ID_ADDR_RAM; //从RAM区读取ID号for (i = 0; i < 7; i++) //读7个字节{SendUart(*iptr++); //发送ID到串口}cptr = ID_ADDR_ROM; //从程序区读取ID号for (i = 0; i < 7; i++) //读7个字节{SendUart(*cptr++); //发送ID到串口}while (1); //程序终止
}
/*----------------------------
串口初始化
----------------------------*/
void InitUart()//115200bps@22.1184MHz
{SCON = 0x50;		//8位数据,可变波特率AUXR = 0x40;                //定时器1为1T模式TMOD = 0x00;                //定时器1为模式0(16位自动重载)TL1 = (65536 - (FOSC/4/BAUD));   //设置波特率重装值TH1 = (65536 - (FOSC/4/BAUD))>>8;TR1 = 1;                    //定时器1开始启动ES = 1;                     //使能串口中断EA = 1;}
/*----------------------------
发送串口数据
----------------------------*/
void SendUart(u8 dat)
{while (busy);               //等待前面的数据发送完成ACC = dat;                  //获取校验位P (PSW.0)busy = 1;SBUF = ACC;                 //写数据到UART数据寄存器
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4
{
//    if (RI)
//    {
//        RI = 0;                 //清除RI位
//    }if (TI){TI = 0;                 //清除TI位busy = 0;               //清忙标志}
}

📚程序源码

复制这段内容后打开百度网盘手机App,操作更方便哦
链接: https://pan.baidu.com/s/1z5i6KBB_6B397_o8QUTEMw
提取码: eaqb
http://www.lryc.cn/news/3905.html

相关文章:

  • Xml格式化与高亮显示
  • 【GlobalMapper精品教程】045:空间分析工具(2)——相交
  • 4年外包终上岸,我只能说这类公司能不去就不去..
  • sklearn降维算法1 - 降维思想与PCA实现
  • 「期末复习」线性代数
  • 伏并网低电压穿越技术
  • opencv的环境搭建
  • C++智能指针
  • MongoDB--》MongoDB数据库以及可视化工具的安装与使用—保姆级教程
  • JAVA 基础题
  • Flutter desktop端多屏幕展示问题处理
  • 每天10个前端小知识 【Day 9】
  • Elasticsearch的读写搜索过程
  • 线上服务质量的问题该如何去处理?你有什么思路?
  • IOC 配置,依赖注入的三种方式
  • 自动机,即有限状态机
  • 第一部分:简单句——第一章:简单句的核心——二、简单句的核心变化(主语/宾语/表语的变化)
  • VSCode Markdown写作引入符合规范的参考文献
  • 电子学会2022年12月青少年软件编程(图形化)等级考试试卷(四级)答案解析
  • JUC并发编程学习笔记(一)——知识补充(Threadlocal和引用类型)
  • 2022级上岸浙理工MBA的复试经验提炼和备考建议
  • 人大金仓数据库索引的应用与日常运维
  • 20230211英语学习
  • 5G图书推荐
  • 【Linux下代码调试工具】gdb 的基本使用
  • UART和RS232、RS485的联系和区别、以及对软件编程的影响
  • ajax是什么?咋实现的
  • AI推理计算框架中的内存优化
  • C语言学习小结(1)——初认识C语言
  • 30分钟吃掉wandb可视化自动调参