本帖最后由 lijianihao 于 2022-5-16 13:35 编辑
DSView解码协议教程入门梦源科技 2022-04-08
版本: 1.0.3一、 前言 在DSView安装目录下,有一个decoders文件夹,里面有许多目录是以各种协议名称命名的。每个目录下有至少2个扩展名为.py的文件,这些都是python代码文件。在linux系统下,decoders目录位于”/usr/local/share/libsigrokdecode4DSL”下。
DSView通过底层python解释器执行python代码,对逻辑分析仪的数据进行解析,按各种算法得出需要的结果。每个协议目录下必须存在两个文件: - __init__.py,用于发现模块,这个文件名左右两边各有两个下划线,这个细节要注意,否则它不会出现在列表中;
- pd.py,用于编写主要的逻辑代码;
这两个文件如何编写,请仔细阅读下面的内容。在1.2.0以上的新版本DSView中,decoders下的有一个名为example目录为示例代码。
二、python入门 python语言是一个解释执行的语言。在官方网站下载并安装好python,就可以进行开发了。
新建一个文本文件,里边输入一行文字:
print('Hello,world!')
保存为 test.py,然后在命令行里输入
python test.py
将会输出“Hello,world!”
这里的python入门只是为了帮助一些读者能够顺利阅读部分协议代码,它所讲的python知识还不够全面和深入,需要读者自行通过其它方式获得python资料,以便提升自己的python编程能力。 - 变量定义
age = 1
name = “Tom” - 数值
1, 1.11, 1000等都属数值型数据 - 字符串
以单引号或双引号括起来的一串字符,表示字符串,如
’abc’
“name” - 列表
[]
[1,2,3]
[1,”abc”,”name”,[7,8,9]]
列表里的元素用逗号隔开,上面的第一个列表是空列表,第二个列表全是数字,第三个列表有多种类型的元素,有数值、字符串、列表。
a = [1,2,3]
变量a是一个列表,通过a[n]方式读取列表里的元素。n的取值从0开始到不超过且不等于列表长度的整数
a[2] = 666
将第3个元素设置成666,列表里的内容可修改
i = a[1]
取列表a的第二个元素赋给变量i - 字典
d = {‘age’:20, ‘name’:’Tome’, ‘data’:[7,8,9]}
字典里的每一项用一对键和值表示。如’age’:20
d[‘name’] = ‘Same’
将字典d的name值设置成’Same’
s = d[‘name’]
取字典d的name值赋给变量s
字典里的键名可以是数字、字符串、元组等类型,如:
{1:'张三'}
{'name':''张三"}
{(1,2,3): "张三"} - 元组
()
(1,2,3)
(2,’abc’)
元组跟列表一样,不同的是用()括起来,元组只能读,不能修改。
注意:当元组只有一个项时,要多打一个逗号,如:
(1,) - 函数
def call(): #普通函数
def call(self): #类成员函数,第一个参数是必须的
def call(a,b,c): #带三个参数的函数
三、新建协议- 新建协议目录
找到存放所有协议的decoders目录。widnows下,它在DSView的安装目录里;
在linux下,它在
/usr/local/share/libsigrokdecode4DSL
打开decoders目录,新建一个子目录,并给目录取名字,要求是能体现协议名称的名字。这里,我们的示列协议名为”lala”。 - __init__.py文件
在bala目录下新建文件“__init__.py”,加入一行如下代码并保存: -
- pd.py文件
在bala目录下,建新pd.py文件,用来编写主要的代码。
四、框架代码模板 以下是解码协议代码框架,写在pd.py文件里。所有协议的代码核心部分是一样的。
下面从c模块继承一个类 到这里,解码协议代码框架模板结束。 五、应用示例 在上面代码框架的基础上,我们接下来实现一个简单的例子。具体是,通过解码某一通道的数据,从一个向上边沿开始到向下边沿结束,输出采样点差值信息。奇数次输出放在第二行,偶数次输出放在第一行。具体编码和说明如下: 六、解码模块工作原理 通过c代码和python代码的互操作,将采样数据交给python分析。经过一系列的处理,最终生成解码结果,用于显示以及供给上层协议作为分析的数据来源。解码模块的核心主要由以下部分组成: - c底层包装类Decoder
在c代码里,给python提供一个经过包装的基类,python可调用基类的一些方法,实现调用c代码的目的。python端通过以下语句导出c代码包装的Decoder类: -
python可访问的Decoder基类的方法有: - register方法
用于注册python输出到c底层的消息类型,有:
(1) OUTPUT_ANN,数据输出到屏幕
(2) OUTPUT_PYTHON,数据输出到上层协议
(3) OUTPUT_BINARY
(4) OUTPUT_META
python调用方式: put方法
输出数据到屏幕或上层协议,python调用方式:
其中,a、b为采样点区间值,self.out_ann为注册的消息类型,[0,[‘abc’]], 0为消息类型序号,参考之前的内容;[‘abc’]为消息内容了 wait方法
获得上一次分析位置后的采样数据,可通过参数指定边沿查找条件。
调用方式: self.wait()
可指定参数,如:{0,’r’}表示第1个绑定的通道满足向上边沿的数据;{1,’f’}表示第2个绑定通道足向下边沿的数据。其它条件标志还有:h、l、e、n。
可通过多个条件组成并和或的条件。并条件如:{0:’f’,1:’r’},或条件如:[{0:’f’},{1:’r’}]
- has_channel方法
用来叛断某个通道是否绑定,python调用方式: -
0是通道序号。
- 属性
c底层类给python提供了两个属性:
a. self.samplenum,wait()调用后的采样数据位置;
b. self.matched,wait()调用后条件参数的匹配结果信息;
python层包装类Decoder
继承至c底层包装的类,由c底层实例化并调用python类的方法,代码如下:
子类Decoder的方法有:
- reset方法
这里做一些变量值的重置,以及类的私有变量的定义。变量的定义如: -
- start方法
在解码任务开始执行前,c底层代码会调用一次start函数,这里主要是做一些初始化工作,比如注册消息类型,如: -
- decode方法
由c底层调用,在解码任务开始时,c底层启动一个线程,然后在线程里调用decode方法。
在这个函数里,一直循环调用wait函数,不断从c底层读取符合边沿条件的数据,如: -
(a,b)元组里的变量数跟声明的chnnaels里声明的通道数一致,包括可选的通道上。
解码任务执行流程: - (1) 解码任务开始启动;
- (2) 上层将采样数据分批推送到底层;
- (3) 底层检测并启动一个线程,该线程调用python层的decode函数,不断处理上层推送的数据;
- (4) python层经过一系列的计算处理,生成解码结果,通过put函数输出到c底层;
- (5) 当所有数据推送完成并经过python层处理,解码任务结束;
七、框架升级更新记录 在DSView版本1.2.0以上,更新以下功能: - end方法
python层的方法,当所有数据处理完成后会被c底层触发 - self.last_samplenum属性
c底层提供的属性,其值为所有数据推送完成后最后的数据样位置。当存在end方法时,该属性将被设置 - 数据多种显示格式
显示的annotation数据部分,可以在2进制、16进制、8进制、10进制、ascii格式间转换。 -
put函数将数据输出c底层,并在屏幕上显示。其中,value为要显示的数据。在输出到时需要转换为16进制的字符串。当需要让数据支持在多种格式间转换时,代码修改如下: -
它是通过在数据部分前加@符号,告诉c底层这一部分内容是数据部分,如:
'@66FB'
如果存在前缀文字,需要将格式部分和数据部分开,如:
['Data:{$}','D:{$}', '@66FB']
{$}是占位符,系统将数据部分格式化后替换掉占位符,就会变成:Data:66FB
|