“嵌入式开发学脚本干嘛”之进制/Byte/Hex处理

关注“嵌入式软件实战派”获得更多精品干货。

 

0x00.什么问题

“我是做嵌入式软件开发的,或者说我只做MCU软件开发,我为什么要学写脚本?”

也许,在你所做的工作中不需要。

但是,你有没有遇到一些问题,或许有更高效的解决方法,例如: 

  1. 你是否曾经遇到过面对一堆十进制数,想转换成十六进制数而到处找快速的转换方法?

  2. Debug的时候抓到一段十六进制数,想将其转换成字符串而不断网上搜方法?

  3. 你是否遇到像将hex文件中的某段内容提取出来转换成数组而用C/C++写了半天程序还有bug?

  4. 供应商给一堆参数,不知道如何快速准确地将其转换成代码?

  5. 老板让你统计下项目的资源使用情况写个报告,而你只能map文件翻了又翻还算不准?

  6. 项目做了一个又一个,重复的代码还是一个个敲或者一段段copy而不知疲倦?

  7. ……

项目我是没办法帮你做的咯,但是应对琐碎重复的工作,我在这还真的有些建议或者方法哦。

这篇文章是把脚本能处理嵌入式开发相关的问题的知识点简单汇总一遍。   

嵌入式软件实战派经常说的一句话:能让电脑做的事,人就别瞎折腾了。

以下用流行的Python3做举例讲解。这次的主要内容是:进制、Byte和Hex的处理。

0x01.进制转换

1. string中的数字转int  

int(x, base=10)方法可以将以0-9+-符号组成的字符串转成int值,如果字符串含义这几个字符以外的字符,会出错。  另外,请注意,这个函数返回值是int,以下测试输出结果是十进制值,别看懵了哦。

 int("1234") # 1234
 int("+100") # 100
 int("-20")  # -20
 int("0x55") # error!

输出

 ---------------------------------------------------------------------------
 
 ValueError                               Traceback (most recent call last)
 
  in 
      2 int("+100") # 100
      3 int("-20") # -20

 ----> 4 int("0x55")

 ValueError: invalid literal for int() with base 10: '0x55'

但是,我确实想讲字符串中的数值转十六进制整数呢?int()默认是十进制的,给它加个进制参数呗。

 int("0xFF",16) # 255 
 int("FF", 16)  # 255

 

诶?是不是二进制、八进制也行?

int("1100",2) # 12
int("1100",8) # 576

 

这么好玩,停不下来了,是不是任意进制都行?随便搞几个试试。

int("1100",7) # 392

再来

int("1100",39)
 ---------------------------------------------------------------------------
 
 ValueError                               Traceback (most recent call last)
 
  in 

 ----> 1 int("1100",39)

 ValueError: int() base must be >= 2 and <= 36

 

呃呃,这个进制参数只能是>= 2 and <= 36

其他的,还有浮点的、复数等转换:

float('-2020')        # -2020.0
float('-1999.023')    # -1999.023

complex('-11.019')       # (-11.19+0j)
complex('-12.0')         # (-12+0j),去除了小数部分
complex('-112')          # (-112+0j)
complex('-122+29j')      # (-122+29j)
complex('-125.0-25.09j') # (-125-25.09j)

​​​​​​​

2. Hex或Byte的转换

下面来点复杂的,将一段字符串转换成一个Byte数组:

s="Hello, Embedded_SW"
for i in s: print("0x%02X, "%ord(i), end='')

​​​​​​​

输出

 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x5F, 0x53, 0x57,

倒过来,Byte数组转字符串:

arr=[0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x5F, 0x53, 0x57]
s=''
for i in arr: s+=chr(i)
print(s)

​​​​​​​输出

 Hello, Embedded_SW

或者,直接用以下函数:

s="48 65 6C 6C 6F 2C 20 45 6D 62 65 64 64 65 64 5F 53 57"
bytes.fromhex(s).decode()

​​​​​​​

输出

 'Hello, Embedded_SW'

3. 二进制和补码等

arr=[0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C]
[bin(i) for i in arr]

​​​​​​​输出

 ['0b1001000', '0b1100101', '0b1101100', '0b1101100', '0b1101111', '0b101100']

当你看汇编的时候,你可能会看到类似这样的数值:mov -230599, R1  这个负数,是一个什么十六进制数?除了用Windows自带的计算器,你还可以这样:

hex(-230599&0xFFFF)

输出

 '0x7b39'

0x02.字节处理

也许上面的还不满足你的需要,这里还有bytes()bytearray()呢。  语法如:

 bytes([source[, encoding[, errors]]])
 bytearray([source[, encoding[, errors]]])

Python3对Python2的Byte方面的应用做了很大改善。  Byte有什么神奇的操作方法?

s = "Embedded_SW"
bytes(s, 'utf8')
# or use s.encode()

​​​​​​​输出

 b'Embedded_SW'

再看

b = b'\xc7\xb6\xc8\xeb\xca\xbd\xc8\xed\xbc\xfe\xca\xb5\xd5\xbd\xc5\xc9'
b.decode('gbk')

​​​​​​​

输出

 '嵌入式软件实战派'

这有什么用?一个简单的场景:你有一个bin文件,想将其转换成C数组  

with open("binfile.bin", 'rb') as f:
    data = f.read()
    # This data is byte type

​​​​​​​

这个data就是你要数据,它是Byte来的。我们姑且不管这个文件操作过程(下面章节会讲)用简单的方式来说明:

data = b'\xc7\xb6\xc8\xeb\xca\xbd\xc8\xed\xbc\xfe\xca\xb5\xd5\xbd\xc5\xc9'
for i in data: print("0x%02X, "%i, end='')
# or use list(data)

​​​​​​​ 0xC7, 0xB6, 0xC8, 0xEB, 0xCA, 0xBD, 0xC8, 0xED, 0xBC, 0xFE, 0xCA, 0xB5, 0xD5, 0xBD, 0xC5, 0xC9,

或者你有个整数数组(内容是某字符串),你想将其转成字符串看看

arr = [229, 181, 140, 229, 133, 165, 229, 188, 143, 232, 189, 175, 228, 187, 182, 229, 174, 158, 230, 136, 152, 230, 180, 190]
bytes(arr).decode()

​​​​​​​输出:

 '嵌入式软件实战派'

 

讲了这么多,bytes和bytearray甚至str有啥区别?

bytes是不变的,bytearray是可变的,即元组和列表的区别  

bytes是byte的序列,而str是unicode的序列。  

str 使用encode方法转化为 bytes  

bytes通过decode转化为str  

其他bytes或者bytearray的方法可以参考str和list的方法,网上的教程很多,在此不累述。

0x03.字符串处理

0x04.文件处理

0x05.Excel操作

后续继续讲解……

 

关注“嵌入式软件实战派”,获得更多脚本技巧。

你可能感兴趣的:(脚本)