给Arduino 设计一个序列号-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 14283|回复: 2

给Arduino 设计一个序列号

[复制链接]
发表于 2017-1-2 18:32 | 显示全部楼层 |阅读模式
之前看到很多朋友询问过如何实现序列号的功能。就是对于每一个 Arduino 都有独立的编码,这样可以实现一些身份识别之类的功能。
最容易实现的就是每次都修改程序中的定义。但是这样用起来耗时很长,并且必须有源程序才行,琢磨了一下,提出一种软件的实现方法,欢迎大家一起讨论。
本文是纯软件的序列号实现,因此通用性会很好,这里使用 Arduino Uno 来实现。
第一个问题是:如何在命令行下进行刷写。首先将IDE中的上传调试功能打开
image001.png
                              
这样你可以看到IDE具体使用了什么上传命令(Arduino IDE 只是一个外壳,具体的编译和上传是由其他程序实现的。IDE只是调用和重定向了运行的结果)
image002.png
具体的话,上面图片中的烧写代码如下:

C:\Users\labz\Documents\arduino\hardware\tools\avr/bin/avrdude-CC:\Users\ labz \Documents\arduino\hardware\tools\avr/etc/avrdude.conf -v-patmega328p -carduino -PCOM18 -b115200 -D -Uflash:w:C:\Users\ labz\AppData\Local\Temp\build3ee88a1b99cef46fdbee27900bbb7d73.tmp/Blink.ino.hex:i

知道了这一行命令,我们可以直接在CMD窗口中输入这个命令从而完成上传的动作。
第二步,直接修改生成的 HEX文件。这里制作一个带有序列号的DEMO。我们定义程序的序列号为20170101,从串口输出这个编号以便检查,代码如下:
[mw_shl_code=applescript,true]String sign="LABZ";
String number="20170101";

// the setup function runs once when you press reset or power the board
void setup() {
  Serial.begin(9600);
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
  Serial.print(number);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(2000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}[/mw_shl_code]

运行结果如下
image003.png

我们的目标就是直接用工具修改这个序列号,然后上传到 Arduino 上。同样是根据前面的命令行,我们可以知道上传的HEX文件位置:
image004.png
用文本编辑软件即可打开这个文件,搜索 4C 41 42 5A (ASCIIABZ, 这就是为什么我们要在代码中定义StringSign,它能帮助我们定位后面的序列号的位置。其实不用这个作为定位手段直接搜索代码中定义的序列号也是可以的)
image005.png
仔细查看,后面的数据 32 30 31 37 30 36 就是我们的序列号 2017”。之后又遇到的问题是,这个HEX文件是有简单的格式的。根据【参考1】,我们可以得知每行最后一个数值是这一行的校验和。例如

:100CE400FB000F019B014C41425A00323031373036

其中的最后一个 36 是校验和计算方法如下:
10+0C+E4+00+FB+00+0F+01+9B+01+4C+41+42+5A+00+32+30+31+37+30=0x4CA校验和的意思是加上一个值之后最后2位会变成00,0xCA+0x36=0x100
假设,我们的目标是将序列号修改为 19731023 =  30 39 37 33 31 30 32 33
经过分析,我们修改如下
:100CE400FB000F019B014C41425A0031393733312B
:040CF4003032330067
其中最后的校验和是通过前面的数值计算得到的。当然,更简单的办法是根据第一步,直接烧写,烧录程序会提醒你的校验和不匹配。例如,我使用错误的检验和,0x36在烧写的时候收到提示,当前计算结果为0x2B:
image006.png
修改完成之后,再次查看,序列号就是我新定义的了。
image007.png

可以看出,使用手工修改还是比较麻烦的,但是掌握了方法,编写自动化的工具也就是分分钟的事情了。
参考:

发表于 2017-1-2 18:59 | 显示全部楼层
每一个AVR都有一个唯一的sn码,datasheet上有读出的方法,这个可以把利用上
 楼主| 发表于 2017-1-2 21:38 | 显示全部楼层
奈何col 发表于 2017-1-2 18:59
每一个AVR都有一个唯一的sn码,datasheet上有读出的方法,这个可以把利用上

翻了一下 datasheet 没有找到唉~

具体叫什么名字?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 14:46 , Processed in 0.086946 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表